| @@ -6,15 +6,15 @@ use std::{ · 5 unmodified lines |
| 6 | }; | 6 | }; |
| 7 | | 7 | |
| 8 | use gix::bstr::ByteSlice; | 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 | use pulldown_cmark::{CowStr, Event, HeadingLevel, OffsetIter, Tag}; | 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 | use crate::{ | 19 | use crate::{ |
| 20 | changelog, | 20 | changelog, |
| @@ -467,59 +467,54 @@ impl<'a> TryFrom<&'a str> for Headline { · 446 unmodified lines |
| 467 | type Error = (); | 467 | type Error = (); |
| 468 | | 468 | |
| 469 | fn try_from(value: &'a str) -> Result<Self, Self::Error> { | 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> { | 474 | fn headline<'a, E: ParserError<&'a str> + FromExternalError<&'a str, ()>>(i: &mut &'a str) -> PResult<Headline, E> { |
| 475 | let hashes = take_while(|c: char| c == '#'); | 475 | let hashes = take_while(0.., |c: char| c == '#'); |
| 476 | let greedy_whitespace = |i| take_while(char::is_whitespace)(i); | 476 | let greedy_whitespace = |i: &mut &'a str| take_while(0.., char::is_whitespace).parse_next(i); |
| 477 | let take_n_digits = |n: usize| { | 477 | let take_n_digits = |
| 478 | map_res(take_while_m_n(n, n, |c: char| c.is_ascii_digit()), |num| { | 478 | |n: usize| take_while(n, |c: char| c.is_ascii_digit()).try_map(|num| u32::from_str(num).map_err(|_| ())); |
| 479 | u32::from_str(num).map_err(|_| ()) | 479 | |
| 480 | }) | 480 | terminated( |
| 481 | }; | 481 | ( |
| 482 | map( | 482 | separated_pair( |
| 483 | terminated( | 483 | hashes, |
| 484 | tuple(( | 484 | greedy_whitespace, |
| 485 | separated_pair( | 485 | alt(( |
| 486 | hashes, | 486 | ( |
| 487 | greedy_whitespace, | 487 | opt("v"), |
| 488 | alt(( | 488 | take_till0(char::is_whitespace) |
| 489 | tuple(( | 489 | .try_map(|v| semver::Version::parse(v).map_err(|_| ()).map(Some)), |
| 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(")"), | | |
| 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 { | 511 | greedy_whitespace, |
| 519 | level: hashes.len(), | 512 | ) |
| 520 | version_prefix: prefix.map_or_else(String::new, ToOwned::to_owned), | 513 | .map(|((hashes, (prefix, version)), date)| Headline { |
| 521 | version, | 514 | level: hashes.len(), |
| 522 | date, | 515 | version_prefix: prefix.map_or_else(String::new, ToOwned::to_owned), |
| 523 | }, | 516 | version, |
| 524 | )(i) | 517 | date, |
| | 518 | }) |
| | 519 | .parse_next(i) |
| 525 | } | 520 | } |