str_queue/
lib.rs

1//! A queue for a string.
2//!
3//! # Summary
4//!
5//! [`StrQueue`] is a queue for UTF-8 sequences.
6//! Strings can be pushed into `StrQueue`, characters can be popped from the
7//! queue, and the queue can be printed or converted into a string.
8//!
9//! # Details
10//!
11//! ## Non-contiguous
12//!
13//! `StrQueue` does not guarantee that the content is stored on a contiguous
14//! memory region. As of writing this document, `StrQueue` internally uses a
15//! ring buffer.
16//!
17//! ## Push
18//!
19//! `StrQueue` accepts not only strings to be pushed, but also arbitrary bytes.
20//! When bytes (including valid UTF-8 strings) are pushed, the things below
21//! (theoretically) happen in order:
22//!
23//! 1.  Bytes are appended to the internal buffer.
24//! 2.  Internal buffers are validated.
25//!       * If the buffer has incomplete bytes at the end of the buffer,
26//!         they are preserved (at least the until the next bytes are added).
27//!           * "Incomplete bytes" here is byte sequence which can be valid
28//!             UTF-8 sequence if appropriate bytes are appended.
29//!       * Other ill-formed bytes than that are replaced with
30//!         [`U+FFFD REPLACEMENT CHARACTER`][`core::char::REPLACEMENT_CHARACTER`]
31//!         using the same rule as
32//!         [`String::from_utf8_lossy`][`alloc::string::String::from_utf8_lossy`].
33//!
34//! ## Pop
35//!
36//! Pop operations are basically performed to characters, rather than raw bytes.
37//! For example, [`StrQueue::pop_char`] pops the first character, not the first byte.
38//! This principle helps the queue to keep the internal bytes valid as UTF-8 string.
39//!
40//! ## Conversion
41//!
42//! When converting a queue into a string, caller can choose how to handle the
43//! possible trailing incomplete bytes.
44//! [`PartialHandling::Ignore`] lets methods ignore such incomplete bytes (if
45//! exist), and [`PartialHandling::Emit`] lets methods emit them as a `U+FFFD
46//! REPLACEMENT CHARACTER`.
47//!
48//! ## Range
49//!
50//! This crate provides adaptors for subrange access: [`BytesRange`] and
51//! [`CharsRange`]. Subrange adaptor types plays a similar role as [`&str`] for
52//! [`String`]: they are views to the subrange of the underlying `StrQueue`.
53//!
54//! [`BytesRange`] can point to arbitrary subrange.
55//! [`CharsRange`] can only point to a subrange that are valid UTF-8 string and
56//! the last possibly incomplete character (i.e. the same condition as
57//! [`StrQueue`].
58//!
59//! # Usage
60//!
61//! ## Creation
62//!
63//! Default queue created by [`StrQueue::new`] is empty.
64//!
65//! ```
66//! use str_queue::{PartialHandling, StrQueue};
67//!
68//! let queue = StrQueue::new();
69//! assert!(queue.display(PartialHandling::Emit).to_string().is_empty());
70//! ```
71//!
72//! A queue can be created with initial contents by [`StrQueue::from`].
73//!
74//! ```
75//! use str_queue::{PartialHandling, StrQueue};
76//!
77//! let queue = StrQueue::from("hello");
78//! assert_eq!(queue.display(PartialHandling::Emit).to_string(), "hello");
79//! ```
80//!
81//! ```
82//! use str_queue::{PartialHandling, StrQueue};
83//!
84//! let queue = StrQueue::from(b"he\xf0llo\xce");
85//! assert_eq!(queue.display(PartialHandling::Emit).to_string(), "he\u{FFFD}llo\u{FFFD}");
86//! ```
87//!
88//! ## Push
89//!
90//! Bytes and string can be pushed.
91//!
92//! ```
93//! use str_queue::{PartialHandling, StrQueue};
94//!
95//! let mut queue = StrQueue::new();
96//!
97//! queue.push_str("hello");
98//! assert_eq!(queue.display(PartialHandling::Emit).to_string(), "hello");
99//!
100//! queue.push_bytes(b" world");
101//! assert_eq!(queue.display(PartialHandling::Emit).to_string(), "hello world");
102//! ```
103//!
104//! ## Pop
105//!
106//! The first characters can be popped using [`StrQueue::pop_char`].
107//!
108//! ```
109//! use str_queue::StrQueue;
110//!
111//! let mut queue = StrQueue::from(b"ab\xf0");
112//! assert_eq!(queue.pop_char(), Some('a'));
113//! assert_eq!(queue.pop_char(), Some('b'));
114//! // Incomplete bytes are simply ignored as they are not a character.
115//! assert_eq!(queue.pop_char(), None);
116//! ```
117//!
118//! The first line can be popped using [`StrQueue::pop_line`].
119//!
120//! ```
121//! use str_queue::StrQueue;
122//!
123//! // Note that the last "world\r" is not considered as a complete line
124//! // since the line can be finally "world\r" or "world\r\n".
125//! let mut queue = StrQueue::from("Hello\nworld\r\nGoodbye\rworld\r");
126//!
127//! // The popped line can be dropped.
128//! queue.pop_line();
129//! // The popped line can be accessed.
130//! assert_eq!(queue.pop_line().map(|v| v.to_string()).as_deref(), Some("world\r\n"));
131//! assert_eq!(queue.pop_line().map(|v| v.to_string()).as_deref(), Some("Goodbye\r"));
132//! assert_eq!(queue.pop_line().map(|v| v.to_string()).as_deref(), None);
133//! assert_eq!(queue.chars_range(..), "world\r");
134//! ```
135//!
136//! ## Ranges
137//!
138//! Bytes ranges can be created by [`StrQueue::bytes_range`] method.
139//!
140//! ```
141//! use str_queue::StrQueue;
142//!
143//! let queue = StrQueue::from("alpha\u{03B1}beta\u{03B2}");
144//! let bytes = queue.bytes_range(6..12);
145//! assert_eq!(bytes, b"\xb1beta\xce"[..]);
146//! ```
147//!
148//! Chars ranges can be created by [`StrQueue::chars_range`] method.
149//! `CharsRange` implements [`Display`][`core::fmt::Display`] and
150//! [`ToString`][`alloc::string::ToString`] traits, since the it is guaranteed
151//! to have a valid string as a prefix (with possibly incomplete character as
152//! a suffix).
153//!
154//! ```
155//! use str_queue::StrQueue;
156//!
157//! let queue = StrQueue::from("alpha\u{03B1}beta\u{03B2}");
158//! let range = queue.chars_range(7..);
159//! assert_eq!(range, "beta\u{03B2}");
160//! assert_eq!(range.to_string(), "beta\u{03B2}");
161//! ```
162//!
163//! Subranges can be created from ranges.
164//!
165//! ```
166//! use str_queue::StrQueue;
167//!
168//! let queue = StrQueue::from("Hello world");
169//! let bytes = queue.bytes_range(6..);
170//! assert_eq!(bytes, b"world"[..]);
171//!
172//! let subrange = bytes.range(1..4);
173//! assert_eq!(subrange, b"orl"[..]);
174//! ```
175//!
176//! ```
177//! use str_queue::StrQueue;
178//!
179//! let queue = StrQueue::from("Hello world");
180//! let range = queue.chars_range(6..);
181//! assert_eq!(range, "world");
182//!
183//! let subrange = range.range(1..4);
184//! assert_eq!(subrange, "orl");
185//! ```
186//!
187//! ## Conversion
188//!
189//! Note that `StrQueue` does not guarantee the content is stored on a
190//! contiguous memory region.
191//! So, you cannot get the content string as a single `&str` without paying
192//! additional cost.
193//!
194//! ### Display
195//!
196//! [`StrQueue::display`] returns a helper struct which implements
197//! [`core::fmt::Display`]. It can be written to a formatter or converted to
198//! a string using `.to_string()`.
199//!
200//! To create [`String`][`alloc::string::String`], use `.to_string()`.
201//!
202//! ```
203//! use str_queue::{PartialHandling, StrQueue};
204//!
205//! let queue = StrQueue::from("hello");
206//!
207//! let s: String = queue.display(PartialHandling::Emit).to_string();
208//! assert_eq!(s, "hello");
209//! ```
210//!
211//! To write the string into a writer, use the return value directly.
212//!
213//! ```
214//! use core::fmt::Write as _;
215//! use str_queue::{PartialHandling, StrQueue};
216//!
217//! let queue = StrQueue::from("hello");
218//! // `String` implements `core::fmt::Write`, and can be used for `write!()`.
219//! let mut buf = String::new();
220//!
221//! write!(buf, "{}", queue.display(PartialHandling::Emit));
222//! assert_eq!(buf, "hello");
223//! ```
224//!
225//! ### Fragments
226//!
227//! [`StrQueue::fragments`] returns an iterator of [`Fragment`]s, which can hold
228//! a substring slices and a characters.
229//!
230//! ```
231//! use str_queue::{Fragment, PartialHandling, StrQueue};
232//!
233//! // Note that `\xce` can appear as a first byte of valid UTF-8 sequence.
234//! let queue = StrQueue::from(b"hello \xce");
235//!
236//! let mut buf = String::new();
237//! for frag in queue.fragments(PartialHandling::Emit) {
238//!     match frag {
239//!         Fragment::Str(s) => buf.push_str(s),
240//!         Fragment::Char(c) => buf.push(c),
241//!         Fragment::Incomplete => buf.push_str("<<incomplete>>"),
242//!     }
243//! }
244//! assert_eq!(buf, "hello <<incomplete>>");
245//! ```
246//!
247//! ### Characters
248//!
249//! [`StrQueue::chars`] and [`StrQueue::into_chars`] return an iterator of [`char`]s.
250//!
251//! `StrQueue::chars` does not consume the queue.
252//!
253//! ```
254//! use str_queue::{PartialHandling, StrQueue};
255//!
256//! let queue = StrQueue::from("hello");
257//! let mut chars = queue.chars(PartialHandling::Emit);
258//! assert_eq!(chars.next(), Some('h'));
259//! assert_eq!(chars.next(), Some('e'));
260//! assert_eq!(chars.next(), Some('l'));
261//! assert_eq!(chars.next(), Some('l'));
262//! assert_eq!(chars.next(), Some('o'));
263//! assert_eq!(chars.next(), None);
264//! // `StrQueue::chars()` does not consume the queue, so it can be used here.
265//! assert_eq!(
266//!     queue.chars(PartialHandling::Emit).collect::<String>(),
267//!     "hello"
268//! );
269//! ```
270//!
271//! `StrQueue::into_chars` consumes the queue.
272//!
273//! ```
274//! use str_queue::{PartialHandling, StrQueue};
275//!
276//! let queue = StrQueue::from("hello");
277//! let mut chars = queue.into_chars(PartialHandling::Emit);
278//! assert_eq!(chars.next(), Some('h'));
279//! assert_eq!(chars.next(), Some('e'));
280//! assert_eq!(chars.next(), Some('l'));
281//! assert_eq!(chars.next(), Some('l'));
282//! assert_eq!(chars.next(), Some('o'));
283//! assert_eq!(chars.next(), None);
284//! // `queue` is no longer available, as it is consumeb dy `queue.into_chars()`.
285//! ```
286#![cfg_attr(not(feature = "std"), no_std)]
287#![forbid(unsafe_code)]
288#![warn(rust_2018_idioms)]
289// `clippy::missing_docs_in_private_items` implies `missing_docs`.
290#![warn(clippy::missing_docs_in_private_items)]
291#![warn(clippy::unwrap_used)]
292
293extern crate alloc;
294
295mod iter;
296mod range;
297mod utf8;
298
299use core::cmp::Ordering;
300use core::fmt;
301use core::hash;
302use core::mem;
303use core::num::NonZeroUsize;
304use core::ops::{Bound, RangeBounds};
305use core::str;
306
307use alloc::collections::VecDeque;
308
309pub use crate::iter::{Chars, Fragment, Fragments, IntoChars};
310pub use crate::range::{BytesRange, CharsRange, CharsRangePoppedLine};
311use crate::utf8::REPLACEMENT_CHAR_STR;
312
313/// Queue for a string.
314///
315/// This queue can contain incomplete UTF-8 byte sequences at the tail.
316/// However, if it became sure that the sequence is invalid as UTF-8 sequence,
317/// the invalid bytes would be replaced by U+FFFD REPLACEMENT CHARACTER.
318#[derive(Default, Debug, Clone)]
319pub struct StrQueue {
320    /// Inner deque.
321    inner: VecDeque<u8>,
322    /// Length of the trailing bytes that are possibly invalid UTF-8 sequence.
323    ///
324    /// This must always be less than 4.
325    len_incomplete: u8,
326}
327
328/// `StrQueue` creation.
329impl StrQueue {
330    /// Creates an empty `StrQueue`.
331    ///
332    /// # Examples
333    ///
334    /// ```
335    /// use str_queue::StrQueue;
336    ///
337    /// let deque = StrQueue::new();
338    /// ```
339    #[inline]
340    #[must_use]
341    pub fn new() -> Self {
342        Self::default()
343    }
344
345    /// Creates an empty `StrQueue` with at least the given capacity.
346    ///
347    /// # Examples
348    ///
349    /// ```
350    /// use str_queue::StrQueue;
351    ///
352    /// let deque = StrQueue::with_capacity(42);
353    ///
354    /// assert!(deque.capacity() >= 42);
355    /// ```
356    #[inline]
357    #[must_use]
358    pub fn with_capacity(capacity: usize) -> Self {
359        Self {
360            inner: VecDeque::with_capacity(capacity),
361            len_incomplete: 0,
362        }
363    }
364}
365
366/// Capacity.
367impl StrQueue {
368    /// Returns the number of bytes the `StrQueue` can hold without reallocating.
369    ///
370    /// # Examples
371    ///
372    /// ```
373    /// use str_queue::StrQueue;
374    ///
375    /// let deque = StrQueue::with_capacity(42);
376    ///
377    /// assert!(deque.capacity() >= 42);
378    /// ```
379    #[inline]
380    #[must_use]
381    pub fn capacity(&self) -> usize {
382        self.inner.capacity()
383    }
384
385    /// Reserves capacity for at least `additional` more bytes.
386    #[inline]
387    pub fn reserve(&mut self, additional: usize) {
388        self.inner.reserve(additional);
389    }
390
391    /// Reserves capacity for exact `additional` more bytes.
392    #[inline]
393    pub fn reserve_exact(&mut self, additional: usize) {
394        self.inner.reserve_exact(additional);
395    }
396
397    /// Shrinks the capacity of the `StrQueue` as much as possible.
398    #[inline]
399    pub fn shrink_to_fit(&mut self) {
400        self.inner.shrink_to_fit();
401    }
402}
403
404/// Subrange access.
405impl StrQueue {
406    /// Returns the subrange accessor for the queue.
407    #[inline]
408    #[must_use]
409    pub fn bytes_range<R>(&self, range: R) -> BytesRange<'_>
410    where
411        R: RangeBounds<usize>,
412    {
413        BytesRange::new(self, range)
414    }
415
416    /// Returns the subrange accessor for the queue.
417    ///
418    /// The returned range can contain an incomplete character at the end.
419    /// If you want to exclude a possible trailing incomplete character in the range,
420    /// use [`CharsRange::to_complete`] or [`CharsRange::trim_last_incomplete_char`].
421    ///
422    /// # Panics
423    ///
424    /// Panics if the start bound of the range does not lie on UTF-8 sequence boundary.
425    #[inline]
426    #[must_use]
427    pub fn chars_range<R>(&self, range: R) -> CharsRange<'_>
428    where
429        R: RangeBounds<usize>,
430    {
431        CharsRange::new(self, range)
432    }
433}
434
435/// Content length and existence.
436impl StrQueue {
437    /// Returns the string length in bytes, including incomplete bytes.
438    ///
439    /// # Examples
440    ///
441    /// ```
442    /// use str_queue::StrQueue;
443    ///
444    /// let queue = StrQueue::from(b"hello\xce");
445    /// assert_eq!(queue.len(), 6);
446    /// ```
447    #[inline]
448    #[must_use]
449    pub fn len(&self) -> usize {
450        self.inner.len()
451    }
452
453    /// Returns true if the queue is completely empty (i.e. has no bytes).
454    ///
455    /// # Examples
456    ///
457    /// ```
458    /// use str_queue::StrQueue;
459    ///
460    /// let mut queue = StrQueue::new();
461    /// assert!(queue.is_empty());
462    ///
463    /// queue.push_str("hello");
464    /// assert!(!queue.is_empty());
465    /// ```
466    #[inline]
467    #[must_use]
468    pub fn is_empty(&self) -> bool {
469        self.inner.is_empty()
470    }
471
472    /// Returns the string length in bytes, excluding incomplete bytes.
473    ///
474    /// # Examples
475    ///
476    /// ```
477    /// use str_queue::StrQueue;
478    ///
479    /// let queue = StrQueue::from(b"hello\xce");
480    /// assert_eq!(queue.len_complete(), 5);
481    /// ```
482    #[inline]
483    #[must_use]
484    pub fn len_complete(&self) -> usize {
485        self.inner.len() - self.len_incomplete()
486    }
487
488    /// Returns the length of incomplete bytes.
489    ///
490    /// # Examples
491    ///
492    /// ```
493    /// use str_queue::StrQueue;
494    ///
495    /// let queue = StrQueue::from(b"hello\xce");
496    /// assert_eq!(queue.len_incomplete(), 1);
497    /// ```
498    #[inline]
499    #[must_use]
500    pub fn len_incomplete(&self) -> usize {
501        usize::from(self.len_incomplete)
502    }
503
504    /// Returns true if the `StrQueue` contains no complete string.
505    ///
506    /// This returns the same value as `self.first().is_none()`.
507    ///
508    /// # Examples
509    ///
510    /// ```
511    /// use str_queue::StrQueue;
512    ///
513    /// let mut queue = StrQueue::new();
514    /// assert!(queue.is_empty_complete());
515    ///
516    /// queue.push_bytes(b"\xce");
517    /// assert!(queue.is_empty_complete());
518    /// assert_eq!(queue.first_char(), None);
519    ///
520    /// queue.push_bytes(b"\xb1");
521    /// assert!(!queue.is_empty_complete());
522    /// assert_eq!(queue.first_char(), Some('\u{03B1}'));
523    /// ```
524    #[inline]
525    #[must_use]
526    pub fn is_empty_complete(&self) -> bool {
527        self.inner.len() == self.len_incomplete as usize
528    }
529
530    /// Returns true if the content is a complete string, i.e. has no trailing
531    /// incomplete character.
532    ///
533    /// # Examples
534    ///
535    /// ```
536    /// use str_queue::StrQueue;
537    ///
538    /// let mut queue = StrQueue::from(b"abc\xce");
539    /// assert!(!queue.is_complete());
540    /// queue.push_bytes(b"\xb1");
541    /// // Now the string is "abc\u{03B1}".
542    /// assert!(queue.is_complete());
543    /// ```
544    pub fn is_complete(&self) -> bool {
545        self.len_incomplete == 0
546    }
547}
548
549/// Buffer and content manipulation.
550impl StrQueue {
551    /// Clears the `StrQueue`, removing all bytes.
552    ///
553    /// # Examples
554    ///
555    /// ```
556    /// use str_queue::{PartialHandling, StrQueue};
557    ///
558    /// let mut queue = StrQueue::from(b"Hello \xce");
559    /// assert!(!queue.is_empty());
560    ///
561    /// queue.clear();
562    /// assert!(queue.is_empty());
563    /// ```
564    #[inline]
565    pub fn clear(&mut self) {
566        self.inner.clear();
567    }
568
569    /// Trims the last incomplete character, and returns the length of the trimmed bytes.
570    ///
571    /// If the string is complete (i.e. no incomplete character follows), does
572    /// nothing and returns 0.
573    ///
574    /// If you want to get a modified copy instead of modifying `self` itself,
575    /// use [`CharsRange::to_complete`].
576    ///
577    /// # Examples
578    ///
579    /// ```
580    /// use str_queue::{PartialHandling, StrQueue};
581    ///
582    /// let mut queue = StrQueue::from(b"Hello \xce");
583    /// assert_eq!(
584    ///     queue.display(PartialHandling::Emit).to_string(),
585    ///     "Hello \u{FFFD}"
586    /// );
587    ///
588    /// queue.trim_last_incomplete_char();
589    /// assert_eq!(queue.display(PartialHandling::Emit).to_string(), "Hello ");
590    /// ```
591    pub fn trim_last_incomplete_char(&mut self) -> usize {
592        self.inner.truncate(self.len_complete());
593        usize::from(mem::replace(&mut self.len_incomplete, 0))
594    }
595
596    /// Pushes the given string to the queue.
597    ///
598    /// # Examples
599    ///
600    /// ```
601    /// use str_queue::{PartialHandling, StrQueue};
602    ///
603    /// let mut queue = StrQueue::from("hello");
604    /// queue.push_str(" world");
605    ///
606    /// assert_eq!(
607    ///     queue.chars(PartialHandling::Emit).collect::<String>(),
608    ///     "hello world"
609    /// );
610    /// ```
611    pub fn push_str(&mut self, s: &str) {
612        if self.len_incomplete != 0 {
613            self.inner.truncate(self.len_complete());
614            self.inner.extend(REPLACEMENT_CHAR_STR.as_bytes());
615            self.len_incomplete = 0;
616        }
617        self.inner.extend(s.as_bytes());
618    }
619
620    /// Pushes the given character to the queue.
621    ///
622    /// # Examples
623    ///
624    /// ```
625    /// use str_queue::{PartialHandling, StrQueue};
626    ///
627    /// let mut queue = StrQueue::from("hello");
628    /// queue.push_char('!');
629    ///
630    /// assert_eq!(
631    ///     queue.chars(PartialHandling::Emit).collect::<String>(),
632    ///     "hello!"
633    /// );
634    /// ```
635    pub fn push_char(&mut self, c: char) {
636        let mut buf = [0_u8; 4];
637        self.push_str(c.encode_utf8(&mut buf));
638    }
639
640    /// Pushes the given bytes to the queue.
641    ///
642    /// Invalid UTF-8 sequences not at the last would be replaced with
643    /// `U+FFFD REPLACEMENT CHARACTER`.
644    /// The last incomplete sequences would be kept, since it might become valid
645    /// when more bytes are appended later.
646    ///
647    /// # Examples
648    ///
649    /// ```
650    /// use str_queue::{PartialHandling, StrQueue};
651    ///
652    /// let mut queue = StrQueue::from(b"alpha \xce");
653    /// assert_eq!(
654    ///     queue.chars(PartialHandling::Emit).collect::<String>(),
655    ///     "alpha \u{FFFD}"
656    /// );
657    ///
658    /// queue.push_bytes(b"\xb1");
659    /// assert_eq!(
660    ///     queue.chars(PartialHandling::Emit).collect::<String>(),
661    ///     "alpha \u{03B1}"
662    /// );
663    /// ```
664    pub fn push_bytes(&mut self, mut bytes: &[u8]) {
665        // Process incomplete bytes.
666        loop {
667            let (rest, has_progress) = self.process_incomplete_bytes(bytes);
668            if !has_progress {
669                break;
670            }
671            bytes = rest;
672        }
673        if self.len_incomplete != 0 {
674            assert!(
675                bytes.is_empty(),
676                "[consistency] it is not expected to give up processing \
677                 incomplete bytes before consuming all the inputs"
678            );
679            return;
680        }
681
682        while !bytes.is_empty() {
683            let e = match str::from_utf8(bytes) {
684                Ok(s) => {
685                    self.inner.extend(s.as_bytes());
686                    return;
687                }
688                Err(e) => e,
689            };
690            let valid_up_to = e.valid_up_to();
691            if let Some(error_len) = e.error_len() {
692                // Replace invalid bytes with U+FFFD, and resume.
693                self.inner.extend(&bytes[..valid_up_to]);
694                self.inner.extend(REPLACEMENT_CHAR_STR.as_bytes());
695                bytes = &bytes[(valid_up_to + error_len)..];
696                continue;
697            } else {
698                self.inner.extend(bytes);
699                self.len_incomplete = (bytes.len() - valid_up_to) as u8;
700                return;
701            }
702        }
703    }
704
705    /// Processes incomplete bytes and returns a pair of the rest input and the progress.
706    ///
707    /// If there are progress, `(_, true)` is returned.
708    /// If no progress can be made, `(_, false)` is returned.
709    fn process_incomplete_bytes<'a>(&mut self, bytes: &'a [u8]) -> (&'a [u8], bool) {
710        let len_incomplete = usize::from(self.len_incomplete);
711        if len_incomplete == 0 {
712            // Nothing to process.
713            return (bytes, false);
714        }
715
716        // Load already-known incomplete bytes.
717        let mut buf = [0_u8; 4];
718        self.inner
719            .range(self.len_complete()..)
720            .zip(&mut buf[..])
721            .for_each(|(src, dest)| *dest = *src);
722        let len_expected = usize::from(utf8::expected_char_len(buf[0]));
723
724        let len_from_input = len_expected.saturating_sub(len_incomplete);
725        let e = if len_from_input != 0 {
726            // Get more bytes.
727            buf[len_incomplete..len_expected].copy_from_slice(&bytes[..len_from_input]);
728            // Check if the bytes became valid UTF-8 sequence.
729            match str::from_utf8(&buf[..len_expected]) {
730                Ok(_) => {
731                    self.inner.extend(&buf[len_incomplete..len_expected]);
732                    self.len_incomplete = 0;
733                    return (&bytes[len_from_input..], true);
734                }
735                Err(e) => e,
736            }
737        } else {
738            // Incomplete bytes might have some valid UTF-8 sequence.
739            // Check if such prefix exists.
740            match str::from_utf8(&buf[..len_expected]) {
741                Ok(_) => {
742                    self.len_incomplete = (len_incomplete - len_expected) as u8;
743                    return (bytes, true);
744                }
745                Err(e) => e,
746            }
747        };
748
749        // Cannot get valid UTF-8 sequence.
750        // Remove leading bytes from incomplete bytes.
751        assert_eq!(
752            e.valid_up_to(),
753            0,
754            "[consistency] the buffer must have no valid leading characters here"
755        );
756        let error_len = match e.error_len() {
757            Some(e) => e,
758            None => {
759                // Not enough input.
760                assert_eq!(
761                    len_from_input,
762                    bytes.len(),
763                    "[consistency] if more inputs are available, bytes must be \
764                     able to be completed or discarded"
765                );
766                return (&bytes[len_from_input..], len_from_input != 0);
767            }
768        };
769        self.inner.truncate(self.len_complete());
770        self.inner.extend(REPLACEMENT_CHAR_STR.as_bytes());
771        self.inner.extend(&buf[error_len..len_expected]);
772        self.len_incomplete = (len_expected - error_len) as u8;
773
774        (&bytes[len_from_input..], true)
775    }
776
777    /// Pops the first character in the buffer and returns it.
778    ///
779    /// Trailing incomplete character is ignored.
780    ///
781    /// # Examples
782    ///
783    /// ```
784    /// use str_queue::StrQueue;
785    ///
786    /// let mut queue = StrQueue::from("hello");
787    ///
788    /// assert_eq!(queue.pop_char(), Some('h'));
789    /// assert_eq!(queue.pop_char(), Some('e'));
790    /// assert_eq!(queue.pop_char(), Some('l'));
791    /// assert_eq!(queue.pop_char(), Some('l'));
792    /// assert_eq!(queue.pop_char(), Some('o'));
793    /// assert_eq!(queue.pop_char(), None);
794    /// assert!(queue.is_empty());
795    /// ```
796    ///
797    /// ```
798    /// use str_queue::StrQueue;
799    ///
800    /// let mut queue = StrQueue::from(b"a\xf0");
801    ///
802    /// assert_eq!(queue.pop_char(), Some('a'));
803    /// assert_eq!(queue.pop_char(), None);
804    /// assert!(!queue.is_empty());
805    /// ```
806    pub fn pop_char(&mut self) -> Option<char> {
807        let (c, len) = self.first_char_and_len()?;
808        self.inner.drain(..usize::from(len));
809
810        Some(c)
811    }
812
813    /// Pops the first character from the queue and returns it.
814    ///
815    /// The trailing incomplete character is replaced with `U+FFFD REPLACEMENT
816    /// CHARACTER`, if available.
817    ///
818    /// # Examples
819    ///
820    /// ```
821    /// use str_queue::StrQueue;
822    ///
823    /// let queue = StrQueue::from(b"abc\xce");
824    /// let mut range = queue.chars_range(..);
825    ///
826    /// assert_eq!(range.pop_char_replaced(), Some('a'));
827    /// assert_eq!(range.pop_char_replaced(), Some('b'));
828    /// assert_eq!(range.pop_char_replaced(), Some('c'));
829    /// assert_eq!(range.pop_char_replaced(), Some('\u{FFFD}'));
830    /// assert_eq!(range.pop_char_replaced(), None);
831    /// ```
832    pub fn pop_char_replaced(&mut self) -> Option<char> {
833        self.pop_char().or_else(|| {
834            if self.is_empty() {
835                return None;
836            }
837            self.inner.clear();
838            Some('\u{FFFD}')
839        })
840    }
841
842    /// Pops the first line in the queue and returns it.
843    ///
844    /// Incomplete lines are ignored.
845    ///
846    /// Note that it is unspecified whether the line will be removed from the queue,
847    /// if the `PoppedLine` value is not dropped while the borrow it holds expires
848    /// (e.g. due to [`core::mem::forget`]).
849    ///
850    /// # Examples
851    ///
852    /// ```
853    /// use str_queue::StrQueue;
854    ///
855    /// // Note that the last "world\r" is not considered as a complete line
856    /// // since the line can be finally "world\r" or "world\r\n".
857    /// let mut queue = StrQueue::from("Hello\nworld\r\nGoodbye\rworld\r");
858    ///
859    /// assert_eq!(queue.pop_line().map(|v| v.to_string()).as_deref(), Some("Hello\n"));
860    /// assert_eq!(queue.pop_line().map(|v| v.to_string()).as_deref(), Some("world\r\n"));
861    /// assert_eq!(queue.pop_line().map(|v| v.to_string()).as_deref(), Some("Goodbye\r"));
862    /// assert_eq!(queue.pop_line().map(|v| v.to_string()).as_deref(), None);
863    /// assert_eq!(queue.chars_range(..), "world\r");
864    /// ```
865    #[inline]
866    pub fn pop_line(&mut self) -> Option<PoppedLine<'_>> {
867        let line_len = self.first_line()?.len();
868        let line_len = NonZeroUsize::new(line_len)
869            .expect("[validity] a complete line must not be empty since it has a line break");
870        Some(PoppedLine {
871            queue: self,
872            line_len,
873        })
874    }
875
876    /// Pops the first [`Fragment`] from the queue and return it.
877    ///
878    /// In other words, takes as much content as possible from the queue.
879    ///
880    /// # Examples
881    ///
882    /// ```
883    /// use str_queue::StrQueue;
884    ///
885    /// let mut queue = StrQueue::from(b"Hello \xce");
886    /// let mut buf = String::new();
887    ///
888    /// while let Some(frag) = queue.pop_fragment() {
889    ///     buf.push_str(&frag.to_string());
890    /// }
891    ///
892    /// assert_eq!(buf, "Hello \u{FFFD}");
893    /// assert!(queue.is_empty());
894    /// ```
895    pub fn pop_fragment(&mut self) -> Option<PoppedFragment<'_>> {
896        if self.inner.is_empty() {
897            return None;
898        }
899
900        let (former, latter) = self.inner.as_slices();
901        if !former.is_empty() {
902            let last_len = utf8::last_char_len_in_last_4bytes(former)
903                .expect("[validity] the queue content must start with valid UTF-8 string");
904            if last_len.is_complete() {
905                return Some(PoppedFragment {
906                    queue: self,
907                    after_state: StateAfterPoppingFragment::Char { latter_consumed: 0 },
908                });
909            }
910            if usize::from(last_len.available) != former.len() {
911                // Non-empty complete string prefix exists.
912                return Some(PoppedFragment {
913                    queue: self,
914                    after_state: StateAfterPoppingFragment::Former {
915                        rest: last_len.available,
916                    },
917                });
918            }
919
920            let len_missing = last_len.len_missing();
921            if last_len.len_missing() <= latter.len() {
922                return Some(PoppedFragment {
923                    queue: self,
924                    after_state: StateAfterPoppingFragment::Char {
925                        latter_consumed: len_missing as u8,
926                    },
927                });
928            }
929
930            return Some(PoppedFragment {
931                queue: self,
932                after_state: StateAfterPoppingFragment::AllConsumed,
933            });
934        }
935
936        let last_len = utf8::last_char_len_in_last_4bytes(latter)
937            .expect("[validity] the queue content must start with valid UTF-8 string");
938        if last_len.is_complete() {
939            return Some(PoppedFragment {
940                queue: self,
941                after_state: StateAfterPoppingFragment::Latter { rest: 0 },
942            });
943        }
944        Some(PoppedFragment {
945            queue: self,
946            after_state: StateAfterPoppingFragment::AllConsumed,
947        })
948    }
949}
950
951/// Content access.
952impl StrQueue {
953    /// Returns the first character in the buffer and its length in bytes.
954    #[must_use]
955    fn first_char_and_len(&self) -> Option<(char, u8)> {
956        let bytes = self.inner.iter().take(4).copied();
957        utf8::take_char(bytes)
958    }
959
960    /// Returns the first character in the buffer.
961    ///
962    /// # Examples
963    ///
964    /// ```
965    /// use str_queue::StrQueue;
966    ///
967    /// let queue = StrQueue::from("hello");
968    ///
969    /// assert_eq!(queue.first_char(), Some('h'));
970    /// ```
971    #[inline]
972    #[must_use]
973    pub fn first_char(&self) -> Option<char> {
974        self.first_char_and_len().map(|(c, _len)| c)
975    }
976
977    /// Returns the first complete line in the buffer.
978    ///
979    /// # Examples
980    ///
981    /// ```
982    /// use str_queue::StrQueue;
983    ///
984    /// let mut queue = StrQueue::from("hello");
985    /// // No complete line.
986    /// assert_eq!(queue.first_line(), None);
987    ///
988    /// queue.push_bytes(b"\r");
989    /// // Still no complete line: "hello\r" is considered incomplete since
990    /// // it cannot be decided whether the line is "hello\r" or "hello\r\n".
991    /// assert_eq!(queue.first_line(), None);
992    ///
993    /// queue.push_bytes(b"\n");
994    /// assert_eq!(
995    ///     queue.first_line().map(|line| line.to_string()).as_deref(),
996    ///     Some("hello\r\n")
997    /// );
998    /// ```
999    #[inline]
1000    #[must_use]
1001    pub fn first_line(&self) -> Option<CharsRange<'_>> {
1002        self.chars_range(..).first_line()
1003    }
1004}
1005
1006/// Iterators.
1007impl StrQueue {
1008    /// Turns the queue into an iterator of the characters.
1009    ///
1010    /// # Examples
1011    ///
1012    /// ```
1013    /// use str_queue::{PartialHandling, StrQueue};
1014    ///
1015    /// let queue = StrQueue::from("alpha \u{03B1} beta \u{03B2}");
1016    ///
1017    /// assert_eq!(
1018    ///     queue.into_chars(PartialHandling::Emit).collect::<String>(),
1019    ///     "alpha \u{03B1} beta \u{03B2}"
1020    /// );
1021    /// ```
1022    ///
1023    /// Trailing possibly invalid bytes (i.e. incomplete characters) can be
1024    /// replaced with `U+FFFD REPLACEMENT CHARACTER`, or be simply ignored.
1025    ///
1026    /// ```
1027    /// use str_queue::{PartialHandling, StrQueue};
1028    ///
1029    /// let mut queue = StrQueue::from(b"alpha->\xce");
1030    ///
1031    /// // The trailing incomplete character is ignored.
1032    /// assert_eq!(
1033    ///     queue.clone().into_chars(PartialHandling::Ignore).collect::<String>(),
1034    ///     "alpha->"
1035    /// );
1036    /// // The trailing incomplete character is replaced with U+FFFD.
1037    /// assert_eq!(
1038    ///     queue.into_chars(PartialHandling::Emit).collect::<String>(),
1039    ///     "alpha->\u{FFFD}"
1040    /// );
1041    /// ```
1042    #[inline]
1043    #[must_use]
1044    pub fn into_chars(self, partial_handling: PartialHandling) -> IntoChars {
1045        IntoChars::new(self, partial_handling)
1046    }
1047
1048    /// Turns the queue into an iterator of the characters.
1049    ///
1050    /// # Examples
1051    ///
1052    /// ```
1053    /// use str_queue::{PartialHandling, StrQueue};
1054    ///
1055    /// let queue = StrQueue::from("alpha \u{03B1} beta \u{03B2}");
1056    ///
1057    /// assert_eq!(
1058    ///     queue.chars(PartialHandling::Emit).collect::<String>(),
1059    ///     "alpha \u{03B1} beta \u{03B2}"
1060    /// );
1061    /// ```
1062    ///
1063    /// Trailing possibly invalid bytes (i.e. incomplete characters) can be
1064    /// replaced with `U+FFFD REPLACEMENT CHARACTER`, or be simply ignored.
1065    ///
1066    /// ```
1067    /// use str_queue::{PartialHandling, StrQueue};
1068    ///
1069    /// let mut queue = StrQueue::from(b"alpha->\xce");
1070    /// // The trailing incomplete character is ignored.
1071    /// assert_eq!(
1072    ///     queue.chars(PartialHandling::Ignore).collect::<String>(),
1073    ///     "alpha->"
1074    /// );
1075    /// // The trailing incomplete character is replaced with U+FFFD.
1076    /// assert_eq!(
1077    ///     queue.chars(PartialHandling::Emit).collect::<String>(),
1078    ///     "alpha->\u{FFFD}"
1079    /// );
1080    ///
1081    /// queue.push_bytes(b"\xb1");
1082    /// assert_eq!(
1083    ///     queue.chars(PartialHandling::Emit).collect::<String>(),
1084    ///     "alpha->\u{03B1}"
1085    /// );
1086    /// ```
1087    #[inline]
1088    #[must_use]
1089    pub fn chars(&self, partial_handling: PartialHandling) -> Chars<'_> {
1090        Chars::new(self, .., partial_handling)
1091    }
1092
1093    /// Returns the chars iterator for the range.
1094    ///
1095    /// # Panics
1096    ///
1097    /// Panics if the start index of the range does not lie on UTF-8 sequence boundary.
1098    ///
1099    /// # Examples
1100    ///
1101    /// ```
1102    /// use str_queue::{Fragment, PartialHandling, StrQueue};
1103    ///
1104    /// let queue = StrQueue::from("alpha\u{03B1}");
1105    ///
1106    /// assert_eq!(
1107    ///     queue.range_chars(3..6, PartialHandling::Emit).collect::<String>(),
1108    ///     "ha\u{FFFD}"
1109    /// );
1110    /// assert_eq!(
1111    ///     queue.range_chars(3..6, PartialHandling::Ignore).collect::<String>(),
1112    ///     "ha"
1113    /// );
1114    /// ```
1115    #[must_use]
1116    pub fn range_chars<R>(&self, range: R, partial_handling: PartialHandling) -> Chars<'_>
1117    where
1118        R: RangeBounds<usize>,
1119    {
1120        Chars::new(self, range, partial_handling)
1121    }
1122
1123    /// Returns an iterator of content fragments.
1124    ///
1125    /// # Examples
1126    ///
1127    /// The code below are redundant since they are intended to show how to use [`Fragment`].
1128    /// To simply create a string from the queue, use [`StrQueue::display`] method.
1129    ///
1130    /// ```
1131    /// use str_queue::{Fragment, PartialHandling, StrQueue};
1132    ///
1133    /// // Note that `\xce` can appear as a first byte of valid UTF-8 sequence.
1134    /// let queue = StrQueue::from(b"hello \xce");
1135    ///
1136    /// let mut buf = String::new();
1137    /// for frag in queue.fragments(PartialHandling::Emit) {
1138    ///     match frag {
1139    ///         Fragment::Str(s) => buf.push_str(s),
1140    ///         Fragment::Char(c) => buf.push(c),
1141    ///         Fragment::Incomplete => buf.push_str("<<incomplete>>"),
1142    ///     }
1143    /// }
1144    /// assert_eq!(buf, "hello <<incomplete>>");
1145    /// ```
1146    ///
1147    /// When `PartialHandling::Ignore` is passed, `Fragment::Incomplete` won't
1148    /// be emitted even if the queue contains trailing incomplete character.
1149    ///
1150    /// ```
1151    /// use str_queue::{Fragment, PartialHandling, StrQueue};
1152    ///
1153    /// // Note that `\xce` can appear as a first byte of valid UTF-8 sequence.
1154    /// let queue = StrQueue::from(b"hello \xce");
1155    ///
1156    /// let mut buf = String::new();
1157    /// for frag in queue.fragments(PartialHandling::Ignore) {
1158    ///     match frag {
1159    ///         Fragment::Str(s) => buf.push_str(s),
1160    ///         Fragment::Char(c) => buf.push(c),
1161    ///         Fragment::Incomplete => unreachable!("`PartialHandling::Ignore` is specified"),
1162    ///     }
1163    /// }
1164    /// assert_eq!(buf, "hello ");
1165    /// ```
1166    ///
1167    /// Note that `StrQueue` will immediately replace non-incomplete invalid
1168    /// bytes (such as `\xff` and `\xce\xff`).
1169    /// Such already-replaced bytes will be printed as `U+FFFD` even if
1170    /// `PartialHandling::Ignore` is specified.
1171    ///
1172    /// ```
1173    /// use str_queue::{Fragment, PartialHandling, StrQueue};
1174    ///
1175    /// // Note that valid UTF-8 sequences can start with `\xf0`, but
1176    /// // never start with `\xf0\xf0`.
1177    /// // So, the first `\xf0` is immediately replaced with U+FFFD, and the
1178    /// // second `\xf0` is considered as a prefix of an incomplete character.
1179    /// let queue = StrQueue::from(b"hello \xf0\xf0");
1180    ///
1181    /// let mut buf = String::new();
1182    /// for frag in queue.fragments(PartialHandling::Emit) {
1183    ///     match frag {
1184    ///         Fragment::Str(s) => buf.push_str(s),
1185    ///         Fragment::Char(c) => buf.push(c),
1186    ///         Fragment::Incomplete => buf.push_str("<<incomplete>>"),
1187    ///     }
1188    /// }
1189    /// assert_eq!(buf, "hello \u{FFFD}<<incomplete>>");
1190    /// ```
1191    ///
1192    /// ```
1193    /// use str_queue::{Fragment, PartialHandling, StrQueue};
1194    ///
1195    /// // Note that valid UTF-8 sequences can start with `\xf0`, but
1196    /// // never start with `\xf0\xf0`.
1197    /// // So, the first `\xf0` is immediately replaced with U+FFFD, and the
1198    /// // second `\xf0` is considered as a prefix of an incomplete character.
1199    /// let queue = StrQueue::from(b"hello \xf0\xf0");
1200    ///
1201    /// let mut buf = String::new();
1202    /// for frag in queue.fragments(PartialHandling::Ignore) {
1203    ///     match frag {
1204    ///         Fragment::Str(s) => buf.push_str(s),
1205    ///         Fragment::Char(c) => buf.push(c),
1206    ///         Fragment::Incomplete => unreachable!("`PartialHandling::Ignore` is specified"),
1207    ///     }
1208    /// }
1209    /// // Note that the first `\xf0` is replaced with `U+FFFD`.
1210    /// assert_eq!(buf, "hello \u{FFFD}");
1211    /// ```
1212    #[inline]
1213    #[must_use]
1214    pub fn fragments(&self, partial_handling: PartialHandling) -> Fragments<'_> {
1215        self.range_fragments(.., partial_handling)
1216    }
1217
1218    /// Returns the fragments iterator for the range.
1219    ///
1220    /// # Panics
1221    ///
1222    /// Panics if the start index of the range does not lie on UTF-8 sequence boundary.
1223    ///
1224    /// # Examples
1225    ///
1226    /// ```
1227    /// use str_queue::{Fragment, PartialHandling, StrQueue};
1228    ///
1229    /// let queue = StrQueue::from("alpha\u{03B1}");
1230    ///
1231    /// assert_eq!(
1232    ///     queue.range_fragments(3..6, PartialHandling::Emit).to_string(),
1233    ///     "ha\u{FFFD}"
1234    /// );
1235    /// assert_eq!(
1236    ///     queue.range_fragments(3..6, PartialHandling::Ignore).to_string(),
1237    ///     "ha"
1238    /// );
1239    /// ```
1240    #[inline]
1241    #[must_use]
1242    pub fn range_fragments<R>(&self, range: R, partial_handling: PartialHandling) -> Fragments<'_>
1243    where
1244        R: RangeBounds<usize>,
1245    {
1246        Fragments::new(self, range, partial_handling)
1247    }
1248
1249    /// Returns an object that implements [`Display`] for printing the content.
1250    ///
1251    /// # Examples
1252    ///
1253    /// ```
1254    /// use str_queue::StrQueue;
1255    /// use str_queue::PartialHandling::{Emit, Ignore};
1256    ///
1257    /// let mut queue = StrQueue::from(b"alpha->\xce");
1258    /// assert_eq!(queue.display(Ignore).to_string(), "alpha->");
1259    /// assert_eq!(queue.display(Emit).to_string(), "alpha->\u{FFFD}");
1260    ///
1261    /// queue.push_bytes(b"\xb1");
1262    /// assert_eq!(queue.display(Ignore).to_string(), "alpha->\u{03B1}");
1263    /// assert_eq!(queue.display(Emit).to_string(), "alpha->\u{03B1}");
1264    /// ```
1265    ///
1266    /// [`Display`]: `fmt::Display`
1267    #[inline]
1268    #[must_use]
1269    pub fn display(&self, partial_handling: PartialHandling) -> Display<'_> {
1270        Display::new(self, partial_handling)
1271    }
1272}
1273
1274impl From<&str> for StrQueue {
1275    #[inline]
1276    fn from(s: &str) -> Self {
1277        let mut this = Self::with_capacity(s.len());
1278        this.push_str(s);
1279        this
1280    }
1281}
1282
1283impl From<&[u8]> for StrQueue {
1284    #[inline]
1285    fn from(s: &[u8]) -> Self {
1286        let mut this = Self::with_capacity(s.len());
1287        this.push_bytes(s);
1288        this
1289    }
1290}
1291
1292impl<const N: usize> From<&[u8; N]> for StrQueue {
1293    #[inline]
1294    fn from(s: &[u8; N]) -> Self {
1295        Self::from(&s[..])
1296    }
1297}
1298
1299impl hash::Hash for StrQueue {
1300    fn hash<H: hash::Hasher>(&self, state: &mut H) {
1301        self.inner.hash(state);
1302    }
1303}
1304
1305/// Handling of suffix bytes of a partial (incomplete) character.
1306#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1307pub enum PartialHandling {
1308    /// Suffix bytes for an incomplete character will be ignored.
1309    Ignore,
1310    /// Suffix bytes for an incomplete character will be visible as
1311    /// `U+FFFD REPLACEMENT CHARACTER`.
1312    Emit,
1313}
1314
1315impl PartialHandling {
1316    /// Returns true if `self` is `Emit`.
1317    #[inline]
1318    #[must_use]
1319    fn is_emit(self) -> bool {
1320        self == Self::Emit
1321    }
1322
1323    /// Returns true if `self` is `Ignore`.
1324    #[inline]
1325    #[must_use]
1326    fn is_ignore(self) -> bool {
1327        self == Self::Ignore
1328    }
1329}
1330
1331/// Helper struct for printing [`StrQueue`].
1332///
1333/// Created by [`StrQueue::display`] method.
1334#[derive(Debug)]
1335pub struct Display<'a> {
1336    /// Queue.
1337    queue: &'a StrQueue,
1338    /// Whether an incomplete character (replaced with U+FFFD) should be emitted.
1339    partial_handling: PartialHandling,
1340}
1341
1342impl<'a> Display<'a> {
1343    /// Creates a new `Display`.
1344    #[inline]
1345    #[must_use]
1346    fn new(queue: &'a StrQueue, partial_handling: PartialHandling) -> Self {
1347        Self {
1348            queue,
1349            partial_handling,
1350        }
1351    }
1352}
1353
1354impl fmt::Display for Display<'_> {
1355    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1356        self.queue
1357            .fragments(self.partial_handling)
1358            .try_for_each(|frag| frag.fmt(f))
1359    }
1360}
1361
1362/// A line popped from [`StrQueue`] using [`pop_line`][`StrQueue::pop_line`] method.
1363///
1364/// Note that it is unspecified whether the line will be removed from the queue,
1365/// if the `PoppedLine` value is not dropped while the borrow it holds expires
1366/// (e.g. due to [`core::mem::forget`]).
1367#[derive(Debug)]
1368pub struct PoppedLine<'a> {
1369    /// Queue.
1370    queue: &'a mut StrQueue,
1371    /// Line length.
1372    ///
1373    /// A complete line cannot be empty since it has a line break.
1374    line_len: NonZeroUsize,
1375}
1376
1377impl<'a> PoppedLine<'a> {
1378    /// Returns the chars range for the line.
1379    #[inline]
1380    #[must_use]
1381    pub fn to_chars_range(&self) -> CharsRange<'_> {
1382        self.queue.chars_range(..self.line_len.get())
1383    }
1384
1385    /// Returns the bytes range for the line.
1386    #[inline]
1387    #[must_use]
1388    pub fn to_bytes_range(&self) -> BytesRange<'_> {
1389        self.queue.bytes_range(..self.line_len.get())
1390    }
1391
1392    /// Returns the length of the line.
1393    #[inline]
1394    #[must_use]
1395    pub fn len(&self) -> usize {
1396        self.line_len.get()
1397    }
1398
1399    /// Returns whether the line is empty, i.e. **always returns false**.
1400    ///
1401    /// A complete line to be removed cannot be empty since it has a line break.
1402    #[inline]
1403    #[must_use]
1404    pub const fn is_empty(&self) -> bool {
1405        false
1406    }
1407}
1408
1409impl fmt::Display for PoppedLine<'_> {
1410    #[inline]
1411    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1412        self.to_chars_range().fmt(f)
1413    }
1414}
1415
1416impl core::ops::Drop for PoppedLine<'_> {
1417    #[inline]
1418    fn drop(&mut self) {
1419        self.queue.inner.drain(..self.line_len.get());
1420    }
1421}
1422
1423impl PartialEq for PoppedLine<'_> {
1424    #[inline]
1425    fn eq(&self, other: &PoppedLine<'_>) -> bool {
1426        self.to_bytes_range().eq(&other.to_bytes_range())
1427    }
1428}
1429
1430impl Eq for PoppedLine<'_> {}
1431
1432impl PartialOrd for PoppedLine<'_> {
1433    #[inline]
1434    fn partial_cmp(&self, rhs: &PoppedLine<'_>) -> Option<Ordering> {
1435        self.to_bytes_range().partial_cmp(&rhs.to_bytes_range())
1436    }
1437}
1438
1439impl Ord for PoppedLine<'_> {
1440    #[inline]
1441    fn cmp(&self, rhs: &PoppedLine<'_>) -> Ordering {
1442        self.to_bytes_range().cmp(&rhs.to_bytes_range())
1443    }
1444}
1445
1446impl PartialEq<str> for PoppedLine<'_> {
1447    #[inline]
1448    fn eq(&self, other: &str) -> bool {
1449        self.to_bytes_range().eq(other.as_bytes())
1450    }
1451}
1452
1453impl PartialOrd<str> for PoppedLine<'_> {
1454    #[inline]
1455    fn partial_cmp(&self, rhs: &str) -> Option<Ordering> {
1456        self.to_bytes_range().partial_cmp(rhs.as_bytes())
1457    }
1458}
1459
1460impl PartialEq<PoppedLine<'_>> for str {
1461    #[inline]
1462    fn eq(&self, other: &PoppedLine<'_>) -> bool {
1463        other.to_bytes_range().eq(self.as_bytes())
1464    }
1465}
1466
1467impl PartialOrd<PoppedLine<'_>> for str {
1468    #[inline]
1469    fn partial_cmp(&self, rhs: &PoppedLine<'_>) -> Option<Ordering> {
1470        rhs.to_bytes_range()
1471            .partial_cmp(self.as_bytes())
1472            .map(Ordering::reverse)
1473    }
1474}
1475
1476impl PartialEq<&str> for PoppedLine<'_> {
1477    #[inline]
1478    fn eq(&self, other: &&str) -> bool {
1479        self.eq(*other)
1480    }
1481}
1482
1483impl PartialOrd<&str> for PoppedLine<'_> {
1484    #[inline]
1485    fn partial_cmp(&self, rhs: &&str) -> Option<Ordering> {
1486        self.partial_cmp(*rhs)
1487    }
1488}
1489
1490impl PartialEq<PoppedLine<'_>> for &str {
1491    #[inline]
1492    fn eq(&self, other: &PoppedLine<'_>) -> bool {
1493        other.eq(*self)
1494    }
1495}
1496
1497impl PartialOrd<PoppedLine<'_>> for &str {
1498    #[inline]
1499    fn partial_cmp(&self, rhs: &PoppedLine<'_>) -> Option<Ordering> {
1500        rhs.partial_cmp(*self).map(Ordering::reverse)
1501    }
1502}
1503
1504/// A state after popping a fragment from a queue.
1505#[derive(Debug, Clone, Copy)]
1506enum StateAfterPoppingFragment {
1507    /// The former buffer is partially consumed.
1508    Former {
1509        /// The unused size in the former buffer at the tail.
1510        ///
1511        /// This must be less than 4 since a complete character is at most
1512        /// 4 bytes in UTF-8.
1513        rest: u8,
1514    },
1515    /// The former is completely consumed and the latter is partially consumed.
1516    Char {
1517        /// The consumed size in the latter buffer at the head.
1518        ///
1519        /// This must be less than 4 since a complete character is at most
1520        /// 4 bytes in UTF-8.
1521        latter_consumed: u8,
1522    },
1523    /// The latter buffer is partially consumed.
1524    Latter {
1525        /// The unused size in the latter buffer at the tail.
1526        ///
1527        /// This must be less than 4 since a complete character is at most
1528        /// 4 bytes in UTF-8.
1529        rest: u8,
1530    },
1531    /// All bytes are consumed.
1532    ///
1533    /// This variant indicates that the buffer is currently not yet empty since
1534    /// the buffer has a trailing incomplete character.
1535    AllConsumed,
1536}
1537
1538/// A fragment popped from [`StrQueue`] using [`pop_fragment`][`StrQueue::pop_fragment`] method.
1539///
1540/// Note that it is unspecified whether the line will be removed from the queue,
1541/// if the `PoppedFragment` value is not dropped while the borrow it holds expires
1542/// (e.g. due to [`core::mem::forget`]).
1543#[derive(Debug)]
1544pub struct PoppedFragment<'a> {
1545    /// Queue.
1546    queue: &'a mut StrQueue,
1547    /// State after popping fragment.
1548    after_state: StateAfterPoppingFragment,
1549}
1550
1551impl<'a> PoppedFragment<'a> {
1552    /// Returns the fragment for the line.
1553    #[inline]
1554    #[must_use]
1555    pub fn to_fragment(&self) -> Fragment<'_> {
1556        use StateAfterPoppingFragment::*;
1557
1558        match self.after_state {
1559            Former { rest } => {
1560                let (former, _) = self.queue.inner.as_slices();
1561                let len = former.len() - usize::from(rest);
1562                let s = str::from_utf8(&former[..len])
1563                    .expect("[consistency] the range must be valid UTF-8 string");
1564                Fragment::Str(s)
1565            }
1566            Char { latter_consumed } => {
1567                let (former, latter) = self.queue.inner.as_slices();
1568                let (c, len) = utf8::take_char(
1569                    former
1570                        .iter()
1571                        .chain(&latter[..usize::from(latter_consumed)])
1572                        .copied(),
1573                )
1574                .expect(
1575                    "[consistency] it should be already validated \
1576                     that a complete character is available",
1577                );
1578                debug_assert_eq!(
1579                    usize::from(len),
1580                    former.len() + usize::from(latter_consumed),
1581                    "[consistency] a character lay on the specified area in the buffers"
1582                );
1583                Fragment::Char(c)
1584            }
1585            Latter { rest } => {
1586                let (_, latter) = self.queue.inner.as_slices();
1587                let len = latter.len() - usize::from(rest);
1588                let s = str::from_utf8(&latter[..len])
1589                    .expect("[consistency] the range must be valid UTF-8 string");
1590                Fragment::Str(s)
1591            }
1592            AllConsumed => Fragment::Incomplete,
1593        }
1594    }
1595
1596    /// Returns the chars range for the line.
1597    #[inline]
1598    #[must_use]
1599    pub fn to_chars_range(&self) -> CharsRange<'_> {
1600        use StateAfterPoppingFragment::*;
1601
1602        match self.after_state {
1603            Former { rest } => {
1604                let (former, _) = self.queue.inner.as_slices();
1605                let len = former.len() - usize::from(rest);
1606                self.queue.chars_range(..len)
1607            }
1608            Char { latter_consumed } => {
1609                let (former, _) = self.queue.inner.as_slices();
1610                debug_assert!(
1611                    former.len() < 4,
1612                    "[consistency] the former buffer must not have a complete character"
1613                );
1614                let end = former.len() + usize::from(latter_consumed);
1615                self.queue.chars_range(..end)
1616            }
1617            Latter { rest } => {
1618                let (former, latter) = self.queue.inner.as_slices();
1619                debug_assert!(
1620                    former.is_empty(),
1621                    "[consistency] the former buffer must have been completely consumed"
1622                );
1623                let len = latter.len() - usize::from(rest);
1624                self.queue.chars_range(..len)
1625            }
1626            AllConsumed => self.queue.chars_range(..),
1627        }
1628    }
1629
1630    /// Returns the bytes range for the line.
1631    #[inline]
1632    #[must_use]
1633    pub fn to_bytes_range(&self) -> BytesRange<'_> {
1634        self.to_chars_range().into()
1635    }
1636
1637    /// Returns the length of the line.
1638    #[inline]
1639    #[must_use]
1640    pub fn len(&self) -> usize {
1641        use StateAfterPoppingFragment::*;
1642
1643        match self.after_state {
1644            Former { rest } => {
1645                let (former, _) = self.queue.inner.as_slices();
1646                former.len() - usize::from(rest)
1647            }
1648            Char { latter_consumed } => {
1649                let (former, _) = self.queue.inner.as_slices();
1650                debug_assert!(
1651                    former.len() < 4,
1652                    "[consistency] the former buffer must not have a complete character"
1653                );
1654                former.len() + usize::from(latter_consumed)
1655            }
1656            Latter { rest } => {
1657                let (former, latter) = self.queue.inner.as_slices();
1658                debug_assert!(
1659                    former.is_empty(),
1660                    "[consistency] the former buffer must have been completely consumed"
1661                );
1662                latter.len() - usize::from(rest)
1663            }
1664            AllConsumed => self.queue.len(),
1665        }
1666    }
1667
1668    /// Returns whether the line is empty, i.e. **always returns false**.
1669    ///
1670    /// A complete line to be removed cannot be empty since it has a line break.
1671    #[inline]
1672    #[must_use]
1673    pub const fn is_empty(&self) -> bool {
1674        false
1675    }
1676}
1677
1678impl fmt::Display for PoppedFragment<'_> {
1679    #[inline]
1680    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1681        self.to_fragment().fmt(f)
1682    }
1683}
1684
1685impl core::ops::Drop for PoppedFragment<'_> {
1686    #[inline]
1687    fn drop(&mut self) {
1688        self.queue.inner.drain(..self.len());
1689    }
1690}
1691
1692impl PartialEq for PoppedFragment<'_> {
1693    #[inline]
1694    fn eq(&self, other: &PoppedFragment<'_>) -> bool {
1695        self.to_bytes_range().eq(&other.to_bytes_range())
1696    }
1697}
1698
1699impl Eq for PoppedFragment<'_> {}
1700
1701impl PartialOrd for PoppedFragment<'_> {
1702    #[inline]
1703    fn partial_cmp(&self, rhs: &PoppedFragment<'_>) -> Option<Ordering> {
1704        self.to_bytes_range().partial_cmp(&rhs.to_bytes_range())
1705    }
1706}
1707
1708impl Ord for PoppedFragment<'_> {
1709    #[inline]
1710    fn cmp(&self, rhs: &PoppedFragment<'_>) -> Ordering {
1711        self.to_bytes_range().cmp(&rhs.to_bytes_range())
1712    }
1713}
1714
1715impl PartialEq<str> for PoppedFragment<'_> {
1716    #[inline]
1717    fn eq(&self, other: &str) -> bool {
1718        self.to_bytes_range().eq(other.as_bytes())
1719    }
1720}
1721
1722impl PartialOrd<str> for PoppedFragment<'_> {
1723    #[inline]
1724    fn partial_cmp(&self, rhs: &str) -> Option<Ordering> {
1725        self.to_bytes_range().partial_cmp(rhs.as_bytes())
1726    }
1727}
1728
1729impl PartialEq<PoppedFragment<'_>> for str {
1730    #[inline]
1731    fn eq(&self, other: &PoppedFragment<'_>) -> bool {
1732        other.to_bytes_range().eq(self.as_bytes())
1733    }
1734}
1735
1736impl PartialOrd<PoppedFragment<'_>> for str {
1737    #[inline]
1738    fn partial_cmp(&self, rhs: &PoppedFragment<'_>) -> Option<Ordering> {
1739        rhs.to_bytes_range()
1740            .partial_cmp(self.as_bytes())
1741            .map(Ordering::reverse)
1742    }
1743}
1744
1745impl PartialEq<&str> for PoppedFragment<'_> {
1746    #[inline]
1747    fn eq(&self, other: &&str) -> bool {
1748        self.eq(*other)
1749    }
1750}
1751
1752impl PartialOrd<&str> for PoppedFragment<'_> {
1753    #[inline]
1754    fn partial_cmp(&self, rhs: &&str) -> Option<Ordering> {
1755        self.partial_cmp(*rhs)
1756    }
1757}
1758
1759impl PartialEq<PoppedFragment<'_>> for &str {
1760    #[inline]
1761    fn eq(&self, other: &PoppedFragment<'_>) -> bool {
1762        other.eq(*self)
1763    }
1764}
1765
1766impl PartialOrd<PoppedFragment<'_>> for &str {
1767    #[inline]
1768    fn partial_cmp(&self, rhs: &PoppedFragment<'_>) -> Option<Ordering> {
1769        rhs.partial_cmp(*self).map(Ordering::reverse)
1770    }
1771}
1772
1773/// Workaround to implement `core::ops::Bound::cloned()`.
1774///
1775/// `core::ops::Bound::cloned()` will be stabilized since Rust 1.55.0.
1776/// Once Rust 1.55.0 is released and MSRV of this crate is bumped, this trait
1777/// can be removed safely.
1778///
1779/// See <https://github.com/rust-lang/rust/issues/61356>.
1780trait BoundExt<T> {
1781    /// Maps a `Bound<&T>` to a `Bound<T>` by cloning the contents of the bound.
1782    fn cloned(self) -> Bound<T>;
1783}
1784
1785impl<T: Clone> BoundExt<T> for Bound<&'_ T> {
1786    fn cloned(self) -> Bound<T> {
1787        match self {
1788            Bound::Included(v) => Bound::Included(v.clone()),
1789            Bound::Excluded(v) => Bound::Excluded(v.clone()),
1790            Bound::Unbounded => Bound::Unbounded,
1791        }
1792    }
1793}