| @@ -6,15 +6,15 @@ use std::{ · 5 unmodified lines |
| 6 | 6 | }; |
| 7 | 7 | |
| 8 | 8 | use gix::bstr::ByteSlice; |
| 9 | | −use nom::{ |
| 10 | | − branch::alt, |
| 11 | | − bytes::complete::{tag, tag_no_case, take_till, take_while, take_while_m_n}, |
| 12 | | − combinator::{all_consuming, map, map_res, opt}, |
| 13 | | − error::{FromExternalError, ParseError}, |
| 14 | | − sequence::{delimited, preceded, separated_pair, terminated, tuple}, |
| 15 | | − Finish, IResult, |
| 16 | | −}; |
| 17 | 9 | use pulldown_cmark::{CowStr, Event, HeadingLevel, OffsetIter, Tag}; |
| 10 | +use winnow::{ |
| 11 | + combinator::alt, |
| 12 | + combinator::opt, |
| 13 | + combinator::{delimited, preceded, separated_pair, terminated}, |
| 14 | + error::{FromExternalError, ParserError}, |
| 15 | + prelude::*, |
| 16 | + token::{tag_no_case, take_till0, take_while}, |
| 17 | +}; |
| 18 | 18 | |
| 19 | 19 | use crate::{ |
| 20 | 20 | changelog, |
| @@ -467,59 +467,54 @@ impl<'a> TryFrom<&'a str> for Headline { · 446 unmodified lines |
| 467 | 467 | type Error = (); |
| 468 | 468 | |
| 469 | 469 | fn try_from(value: &'a str) -> Result<Self, Self::Error> { |
| 470 | | − all_consuming(headline::<()>)(value).finish().map(|(_, h)| h) |
| 470 | + headline::<()>.parse(value).map_err(|err| err.into_inner()) |
| 471 | 471 | } |
| 472 | 472 | } |
| 473 | 473 | |
| 474 | | −fn headline<'a, E: ParseError<&'a str> + FromExternalError<&'a str, ()>>(i: &'a str) -> IResult<&'a str, Headline, E> { |
| 475 | | − let hashes = take_while(|c: char| c == '#'); |
| 476 | | − let greedy_whitespace = |i| take_while(char::is_whitespace)(i); |
| 477 | | − let take_n_digits = |n: usize| { |
| 478 | | − map_res(take_while_m_n(n, n, |c: char| c.is_ascii_digit()), |num| { |
| 479 | | − u32::from_str(num).map_err(|_| ()) |
| 480 | | − }) |
| 481 | | − }; |
| 482 | | − map( |
| 483 | | − terminated( |
| 484 | | − tuple(( |
| 485 | | − separated_pair( |
| 486 | | − hashes, |
| 487 | | − greedy_whitespace, |
| 488 | | − alt(( |
| 489 | | − tuple(( |
| 490 | | − opt(tag("v")), |
| 491 | | − map_res(take_till(char::is_whitespace), |v| { |
| 492 | | − semver::Version::parse(v).map_err(|_| ()).map(Some) |
| 493 | | − }), |
| 494 | | − )), |
| 495 | | − map(tag_no_case("unreleased"), |_| (None, None)), |
| 496 | | − )), |
| 497 | | − ), |
| 498 | | − opt(preceded( |
| 499 | | − greedy_whitespace, |
| 500 | | − delimited( |
| 501 | | − tag("("), |
| 502 | | − map_res( |
| 503 | | − tuple((take_n_digits(4), tag("-"), take_n_digits(2), tag("-"), take_n_digits(2))), |
| 504 | | − |(year, _, month, _, day)| { |
| 505 | | − time::Month::try_from(month as u8).map_err(|_| ()).and_then(|month| { |
| 506 | | − time::Date::from_calendar_date(year as i32, month, day as u8) |
| 507 | | − .map_err(|_| ()) |
| 508 | | − .map(|d| d.midnight().assume_utc()) |
| 509 | | − }) |
| 510 | | − }, |
| 511 | | − ), |
| 512 | | − tag(")"), |
| 474 | +fn headline<'a, E: ParserError<&'a str> + FromExternalError<&'a str, ()>>(i: &mut &'a str) -> PResult<Headline, E> { |
| 475 | + let hashes = take_while(0.., |c: char| c == '#'); |
| 476 | + let greedy_whitespace = |i: &mut &'a str| take_while(0.., char::is_whitespace).parse_next(i); |
| 477 | + let take_n_digits = |
| 478 | + |n: usize| take_while(n, |c: char| c.is_ascii_digit()).try_map(|num| u32::from_str(num).map_err(|_| ())); |
| 479 | + |
| 480 | + terminated( |
| 481 | + ( |
| 482 | + separated_pair( |
| 483 | + hashes, |
| 484 | + greedy_whitespace, |
| 485 | + alt(( |
| 486 | + ( |
| 487 | + opt("v"), |
| 488 | + take_till0(char::is_whitespace) |
| 489 | + .try_map(|v| semver::Version::parse(v).map_err(|_| ()).map(Some)), |
| 513 | 490 | ), |
| 491 | + tag_no_case("unreleased").map(|_| (None, None)), |
| 514 | 492 | )), |
| 493 | + ), |
| 494 | + opt(preceded( |
| 495 | + greedy_whitespace, |
| 496 | + delimited( |
| 497 | + "(", |
| 498 | + (take_n_digits(4), "-", take_n_digits(2), "-", take_n_digits(2)).try_map( |
| 499 | + |(year, _, month, _, day)| { |
| 500 | + time::Month::try_from(month as u8).map_err(|_| ()).and_then(|month| { |
| 501 | + time::Date::from_calendar_date(year as i32, month, day as u8) |
| 502 | + .map_err(|_| ()) |
| 503 | + .map(|d| d.midnight().assume_utc()) |
| 504 | + }) |
| 505 | + }, |
| 506 | + ), |
| 507 | + ")", |
| 508 | + ), |
| 515 | 509 | )), |
| 516 | | − greedy_whitespace, |
| 517 | 510 | ), |
| 518 | | − |((hashes, (prefix, version)), date)| Headline { |
| 519 | | − level: hashes.len(), |
| 520 | | − version_prefix: prefix.map_or_else(String::new, ToOwned::to_owned), |
| 521 | | − version, |
| 522 | | − date, |
| 523 | | − }, |
| 524 | | − )(i) |
| 511 | + greedy_whitespace, |
| 512 | + ) |
| 513 | + .map(|((hashes, (prefix, version)), date)| Headline { |
| 514 | + level: hashes.len(), |
| 515 | + version_prefix: prefix.map_or_else(String::new, ToOwned::to_owned), |
| 516 | + version, |
| 517 | + date, |
| 518 | + }) |
| 519 | + .parse_next(i) |
| 525 | 520 | } |