From 7060fc090043448813ff8dc22e5da1e5e62f5ee7 Mon Sep 17 00:00:00 2001 From: Abdul Rahman Sibahi Date: Wed, 19 Mar 2025 20:18:52 +0300 Subject: [PATCH 1/7] added generic paramter for streaming mode in iterator --- src/combinator/mod.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/combinator/mod.rs b/src/combinator/mod.rs index fe6655b98..5ed1657c4 100644 --- a/src/combinator/mod.rs +++ b/src/combinator/mod.rs @@ -887,7 +887,7 @@ where /// assert_eq!(parsed, [("abc", 3usize), ("defg", 4), ("hijkl", 5), ("mnopqr", 6)].iter().cloned().collect()); /// assert_eq!(res, Ok(("123", ()))); /// ``` -pub fn iterator(input: Input, f: F) -> ParserIterator +pub fn iterator(input: Input, f: F) -> ParserIterator where F: Parser, Error: ParseError, @@ -896,17 +896,29 @@ where iterator: f, input, state: Some(State::Running), + _streaming: PhantomData } } /// Main structure associated to the [iterator] function. -pub struct ParserIterator { +pub struct ParserIterator { iterator: F, input: I, state: Option>, + _streaming: std::marker::PhantomData + } -impl ParserIterator { +impl ParserIterator { + /// Returns the remaining input if parsing was successful, or the error if we encountered an error. + pub fn finish(mut self) -> IResult { + match self.state.take().unwrap() { + State::Incomplete(_) | State::Running | State::Done => Ok((self.input, ())), + State::Failure(e) => Err(Err::Failure(e)), + } + } +} +impl ParserIterator { /// Returns the remaining input if parsing was successful, or the error if we encountered an error. pub fn finish(mut self) -> IResult { match self.state.take().unwrap() { @@ -917,10 +929,11 @@ impl ParserIterator { } } -impl core::iter::Iterator for ParserIterator +impl core::iter::Iterator for ParserIterator where F: Parser, Input: Clone, + S: IsStreaming { type Item = Output; @@ -928,7 +941,7 @@ where if let State::Running = self.state.take().unwrap() { let input = self.input.clone(); - match (self.iterator).parse(input) { + match (self.iterator).process::>(input) { Ok((i, o)) => { self.input = i; self.state = Some(State::Running); From d150cef15ad9c0423fef13b10e1d68dfa27bc43a Mon Sep 17 00:00:00 2001 From: Abdul Rahman Sibahi Date: Wed, 19 Mar 2025 20:34:27 +0300 Subject: [PATCH 2/7] add dcos --- src/combinator/mod.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/combinator/mod.rs b/src/combinator/mod.rs index 5ed1657c4..26505f9eb 100644 --- a/src/combinator/mod.rs +++ b/src/combinator/mod.rs @@ -869,8 +869,9 @@ where /// Creates an iterator from input data and a parser. /// -/// Call the iterator's [ParserIterator::finish] method to get the remaining input if successful, -/// or the error value if we encountered an error. +/// Call the iterator's [ParserIterator::finish] method (or [ParserIterator::finish_complete] for +/// complete parsers) to get the remaining input if successful, or the error value if we encountered +/// an error. /// /// On [`Err::Error`], iteration will stop. To instead chain an error up, see [`cut`]. /// @@ -901,7 +902,7 @@ where } /// Main structure associated to the [iterator] function. -pub struct ParserIterator { +pub struct ParserIterator { iterator: F, input: I, state: Option>, @@ -911,13 +912,16 @@ pub struct ParserIterator { impl ParserIterator { /// Returns the remaining input if parsing was successful, or the error if we encountered an error. - pub fn finish(mut self) -> IResult { + /// + /// To be used for Complete parsers + pub fn finish_complete(mut self) -> IResult { match self.state.take().unwrap() { State::Incomplete(_) | State::Running | State::Done => Ok((self.input, ())), State::Failure(e) => Err(Err::Failure(e)), } } } + impl ParserIterator { /// Returns the remaining input if parsing was successful, or the error if we encountered an error. pub fn finish(mut self) -> IResult { From 2018c971e846707d30cc425099934cbf7306ef3f Mon Sep 17 00:00:00 2001 From: Abdul Rahman Sibahi Date: Wed, 19 Mar 2025 20:53:07 +0300 Subject: [PATCH 3/7] added proper trait bound --- src/combinator/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/combinator/mod.rs b/src/combinator/mod.rs index 26505f9eb..555f9d577 100644 --- a/src/combinator/mod.rs +++ b/src/combinator/mod.rs @@ -891,6 +891,7 @@ where pub fn iterator(input: Input, f: F) -> ParserIterator where F: Parser, + S: IsStreaming, Error: ParseError, { ParserIterator { @@ -907,7 +908,6 @@ pub struct ParserIterator { input: I, state: Option>, _streaming: std::marker::PhantomData - } impl ParserIterator { From 5aa033a94eaa5f805da61e9d36e82faa05c09b58 Mon Sep 17 00:00:00 2001 From: Abdul Rahman Sibahi Date: Wed, 19 Mar 2025 21:17:24 +0300 Subject: [PATCH 4/7] adjusted test --- tests/issues.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/issues.rs b/tests/issues.rs index 2b1923d6a..affdbb9b8 100644 --- a/tests/issues.rs +++ b/tests/issues.rs @@ -264,7 +264,7 @@ fn issue_1586_parser_iterator_impl() { } fn parse_input(i: &str) -> impl Iterator + '_ { - iterator(i, parse_line).map(|x| x.parse::().unwrap()) + iterator::<_, _, _, nom::Streaming>(i, parse_line).map(|x| x.parse::().unwrap()) } assert_eq!(parse_input("123\n456").collect::>(), vec![123, 456]); From f9ffbf5beb4f4de5f9cde6f777940bc76232bf60 Mon Sep 17 00:00:00 2001 From: Abdul Rahman Sibahi Date: Fri, 21 Mar 2025 05:20:32 +0300 Subject: [PATCH 5/7] alternate, backwards compatible solution --- src/combinator/mod.rs | 40 ++++++++++++++++++++-------------------- tests/issues.rs | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/combinator/mod.rs b/src/combinator/mod.rs index 555f9d577..8a90e2968 100644 --- a/src/combinator/mod.rs +++ b/src/combinator/mod.rs @@ -869,9 +869,8 @@ where /// Creates an iterator from input data and a parser. /// -/// Call the iterator's [ParserIterator::finish] method (or [ParserIterator::finish_complete] for -/// complete parsers) to get the remaining input if successful, or the error value if we encountered -/// an error. +/// Call the iterator's [ParserIterator::finish] method to get the remaining +/// input if successful, or the error value if we encountered an error. /// /// On [`Err::Error`], iteration will stop. To instead chain an error up, see [`cut`]. /// @@ -888,17 +887,30 @@ where /// assert_eq!(parsed, [("abc", 3usize), ("defg", 4), ("hijkl", 5), ("mnopqr", 6)].iter().cloned().collect()); /// assert_eq!(res, Ok(("123", ()))); /// ``` -pub fn iterator(input: Input, f: F) -> ParserIterator +pub fn iterator(input: Input, f: F) -> ParserIterator +where + F: Parser, + Error: ParseError, +{ + ParserIterator { + iterator: f, + input, + state: Some(State::Running), + _streaming: PhantomData, + } +} + +/// Same as [iterator] but for complete parsers +pub fn iterator_complete(input: Input, f: F) -> ParserIterator where F: Parser, - S: IsStreaming, Error: ParseError, { ParserIterator { iterator: f, input, state: Some(State::Running), - _streaming: PhantomData + _streaming: PhantomData, } } @@ -910,19 +922,7 @@ pub struct ParserIterator { _streaming: std::marker::PhantomData } -impl ParserIterator { - /// Returns the remaining input if parsing was successful, or the error if we encountered an error. - /// - /// To be used for Complete parsers - pub fn finish_complete(mut self) -> IResult { - match self.state.take().unwrap() { - State::Incomplete(_) | State::Running | State::Done => Ok((self.input, ())), - State::Failure(e) => Err(Err::Failure(e)), - } - } -} - -impl ParserIterator { +impl ParserIterator { /// Returns the remaining input if parsing was successful, or the error if we encountered an error. pub fn finish(mut self) -> IResult { match self.state.take().unwrap() { @@ -937,7 +937,7 @@ impl core::iter::Iterator for ParserIterator, Input: Clone, - S: IsStreaming + S: IsStreaming, { type Item = Output; diff --git a/tests/issues.rs b/tests/issues.rs index affdbb9b8..2b1923d6a 100644 --- a/tests/issues.rs +++ b/tests/issues.rs @@ -264,7 +264,7 @@ fn issue_1586_parser_iterator_impl() { } fn parse_input(i: &str) -> impl Iterator + '_ { - iterator::<_, _, _, nom::Streaming>(i, parse_line).map(|x| x.parse::().unwrap()) + iterator(i, parse_line).map(|x| x.parse::().unwrap()) } assert_eq!(parse_input("123\n456").collect::>(), vec![123, 456]); From 1c12c641dfc030f38879355c354f50d874ad86d9 Mon Sep 17 00:00:00 2001 From: Abdul Rahman Sibahi Date: Fri, 21 Mar 2025 05:45:13 +0300 Subject: [PATCH 6/7] remove pointless panic source (unrelated to the topic of this branch) --- src/combinator/mod.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/combinator/mod.rs b/src/combinator/mod.rs index 8a90e2968..af6f940cc 100644 --- a/src/combinator/mod.rs +++ b/src/combinator/mod.rs @@ -895,7 +895,7 @@ where ParserIterator { iterator: f, input, - state: Some(State::Running), + state: State::Running, _streaming: PhantomData, } } @@ -909,7 +909,7 @@ where ParserIterator { iterator: f, input, - state: Some(State::Running), + state: State::Running, _streaming: PhantomData, } } @@ -918,14 +918,14 @@ where pub struct ParserIterator { iterator: F, input: I, - state: Option>, + state: State, _streaming: std::marker::PhantomData } impl ParserIterator { /// Returns the remaining input if parsing was successful, or the error if we encountered an error. - pub fn finish(mut self) -> IResult { - match self.state.take().unwrap() { + pub fn finish(self) -> IResult { + match self.state { State::Running | State::Done => Ok((self.input, ())), State::Failure(e) => Err(Err::Failure(e)), State::Incomplete(i) => Err(Err::Incomplete(i)), @@ -942,25 +942,24 @@ where type Item = Output; fn next(&mut self) -> Option { - if let State::Running = self.state.take().unwrap() { + if let State::Running = self.state { let input = self.input.clone(); match (self.iterator).process::>(input) { Ok((i, o)) => { self.input = i; - self.state = Some(State::Running); Some(o) } Err(Err::Error(_)) => { - self.state = Some(State::Done); + self.state = State::Done; None } Err(Err::Failure(e)) => { - self.state = Some(State::Failure(e)); + self.state = State::Failure(e); None } Err(Err::Incomplete(i)) => { - self.state = Some(State::Incomplete(i)); + self.state = State::Incomplete(i); None } } From bde59417b4ac00e72cfff4f2a5b13d7edcfce0d9 Mon Sep 17 00:00:00 2001 From: Abdul Rahman Sibahi Date: Fri, 21 Mar 2025 05:50:01 +0300 Subject: [PATCH 7/7] cargo fmt --- src/combinator/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/combinator/mod.rs b/src/combinator/mod.rs index af6f940cc..df847f5e8 100644 --- a/src/combinator/mod.rs +++ b/src/combinator/mod.rs @@ -901,7 +901,10 @@ where } /// Same as [iterator] but for complete parsers -pub fn iterator_complete(input: Input, f: F) -> ParserIterator +pub fn iterator_complete( + input: Input, + f: F, +) -> ParserIterator where F: Parser, Error: ParseError, @@ -919,7 +922,7 @@ pub struct ParserIterator { iterator: F, input: I, state: State, - _streaming: std::marker::PhantomData + _streaming: std::marker::PhantomData, } impl ParserIterator {