From 07b9f07ed595dd625beb8a48b2887e2ace122ee7 Mon Sep 17 00:00:00 2001 From: TimLuq Date: Sun, 18 Aug 2024 17:52:10 +0200 Subject: [PATCH] added `take_line` for strings --- src/queue/byte_queue.rs | 2 +- src/queue/string_queue.rs | 22 +++++++++++++++++++--- src/stringdata.rs | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/queue/byte_queue.rs b/src/queue/byte_queue.rs index 27abe20..8bf39ac 100644 --- a/src/queue/byte_queue.rs +++ b/src/queue/byte_queue.rs @@ -467,7 +467,7 @@ impl<'a> ByteQueue<'a> { let (start, end) = self.check_range(range); super::DrainBytes::new(self, start, end) } - + /// Move data to the returned `ByteQueue` until the byte predicate returns `false`. #[inline] #[must_use] diff --git a/src/queue/string_queue.rs b/src/queue/string_queue.rs index 68cf069..f7ba952 100644 --- a/src/queue/string_queue.rs +++ b/src/queue/string_queue.rs @@ -365,14 +365,16 @@ impl<'a> StringQueue<'a> { // SAFETY: The range is checked to be valid UTF-8. unsafe { super::DrainChars::new(self, start, end) } } - + /// Find the first byte position of a char in the queue. #[inline] #[must_use] pub fn find_char bool>(&mut self, mut fun: F) -> Option { - self.chars_indecies().find(|&(_, ch)| fun(ch)).map(|(position, _)| position) + self.chars_indecies() + .find(|&(_, ch)| fun(ch)) + .map(|(position, _)| position) } - + /// Move data to the returned `StringQueue` until the char predicate returns `false`. #[inline] #[must_use] @@ -387,6 +389,20 @@ impl<'a> StringQueue<'a> { core::mem::swap(&mut self.queue, &mut ret); Self { queue: ret } } + + /// Takes and removes the first line from the queue. + /// If a newline (`'\n'`) is found, the returned queue will contain all data up to, and including, the newline. + /// If the queue does not contain a newline character, the returned queue will contain all data currently in the queue. + #[inline] + #[must_use] + pub fn take_line(&mut self) -> Self { + let Some(position) = self.find_char(|ch| ch == '\n') else { + return core::mem::replace(self, Self::new()); + }; + let mut ret = self.queue.split_off(position + 1); + core::mem::swap(&mut self.queue, &mut ret); + Self { queue: ret } + } } impl<'a> From> for StringQueue<'a> { diff --git a/src/stringdata.rs b/src/stringdata.rs index 7ffa65f..34bff05 100644 --- a/src/stringdata.rs +++ b/src/stringdata.rs @@ -312,6 +312,20 @@ impl<'a> StringData<'a> { av } + /// Takes and removes the first line from the string. + /// If a newline (`'\n'`) is found, the returned string will contain all data up to, and including, the newline. + /// If the queue does not contain a newline character, the returned string will contain all data currently in the queue. + #[inline] + #[must_use] + pub fn take_line(&mut self) -> Self { + let Some(position) = self.as_str().find('\n') else { + return core::mem::replace(self, Self::empty()); + }; + let av = self.sliced(0..position); + self.make_sliced(position..); + av + } + /// Split the `StringData` at the given position. #[inline] #[must_use]