str_queue/range/
chars.rs

1//! Chars range in a queue.
2
3use core::cmp::Ordering;
4use core::fmt;
5use core::num::NonZeroUsize;
6use core::ops::{Bound, RangeBounds};
7
8use crate::iter::{Chars, Fragment, Fragments};
9use crate::range::BytesRange;
10use crate::utf8::{self, REPLACEMENT_CHAR};
11use crate::StrQueue;
12// `BoundExt` trait is a workaround until Rust 1.55.0.
13// Suppress `unused_imports` for Rust 1.55.0 beta or later, for now.
14#[allow(unused_imports)]
15use crate::BoundExt;
16
17/// An internal error type indicating the character is incomplete.
18#[derive(Debug, Clone, Copy)]
19struct IncompleteCharError;
20
21/// Subrange of a `StrQueue`.
22///
23/// This can be created by [`StrQueue::chars_range`].
24///
25/// The range contains valid UTF-8 sequence with the optional
26/// last incomplete character.
27#[derive(Debug, Clone, Copy, Eq, Hash)]
28pub struct CharsRange<'a> {
29    /// The range.
30    range: BytesRange<'a>,
31}
32
33/// Setup.
34impl<'a> CharsRange<'a> {
35    /// Creates a new `CharsRange` for the queue.
36    ///
37    /// # Panics
38    ///
39    /// Panics if the start bound of the range does not lie on UTF-8 sequence boundary.
40    #[must_use]
41    pub(crate) fn new<R>(queue: &'a StrQueue, range: R) -> Self
42    where
43        R: RangeBounds<usize>,
44    {
45        let (former, latter) = queue.inner.as_slices();
46        #[allow(unstable_name_collisions)] // This is intended. See `crate::BoundExt` trait.
47        Self::from_slices_and_bounds(
48            former,
49            latter,
50            range.start_bound().cloned(),
51            range.end_bound().cloned(),
52        )
53    }
54
55    /// Creates `CharsRange` from slices and range bounds.
56    ///
57    /// # Panics
58    ///
59    /// Panics if the start bound of the range does not lie on UTF-8 sequence boundary.
60    /// Panics if `former` and `latter` overlaps.
61    /// Panics if the given index is out of range.
62    #[must_use]
63    fn from_slices_and_bounds(
64        former: &'a [u8],
65        latter: &'a [u8],
66        start: Bound<usize>,
67        end: Bound<usize>,
68    ) -> Self {
69        let range = BytesRange::from_slices_and_bounds(former, latter, start, end);
70
71        // Check if the first byte of the index is the start byte of a character.
72        if !matches!(start, Bound::Unbounded | Bound::Included(0))
73            && range.first().map(utf8::expected_char_len) == Some(0)
74        {
75            panic!(
76                "[precondition] start bound of the range {:?} \
77                 does not lie on UTF-8 sequence boundary",
78                (start, end)
79            );
80        }
81
82        Self { range }
83    }
84}
85
86/// Subrange access.
87impl<'a> CharsRange<'a> {
88    /// Returns the subrange.
89    ///
90    /// The returned range can contain an incomplete character at the end.
91    /// If you want to exclude a possible trailing incomplete character in the range,
92    /// use [`CharsRange::to_complete`] or [`CharsRange::trim_last_incomplete_char`].
93    ///
94    /// # Panics
95    ///
96    /// Panics if the start bound of the range does not lie on UTF-8 sequence boundary.
97    /// Panics if the given index is out of range.
98    ///
99    /// # Examples
100    ///
101    /// ```
102    /// use str_queue::StrQueue;
103    ///
104    /// let queue = StrQueue::from(b"Hello \xce\xb1");
105    /// let range = queue.chars_range(..);
106    /// assert_eq!(range.to_string(), "Hello \u{03B1}");
107    ///
108    /// assert_eq!(range.range(3..7).to_string(), "lo \u{FFFD}");
109    /// ```
110    #[must_use]
111    pub fn range<R>(&self, range: R) -> Self
112    where
113        R: RangeBounds<usize>,
114    {
115        #[allow(unstable_name_collisions)] // This is intended. See `crate::BoundExt` trait.
116        Self::from_slices_and_bounds(
117            self.range.former,
118            self.range.latter,
119            range.start_bound().cloned(),
120            range.end_bound().cloned(),
121        )
122    }
123
124    /// Returns the range without the last incomplete character.
125    ///
126    /// If you want to modify `self` instead of getting a modified copy, use
127    /// [`CharsRange::trim_last_incomplete_char`].
128    ///
129    /// # Examples
130    ///
131    /// ```
132    /// use str_queue::{PartialHandling, StrQueue};
133    ///
134    /// let queue = StrQueue::from(b"Hello \xce");
135    /// let range = queue.chars_range(..);
136    /// assert_eq!(range.to_string(), "Hello \u{FFFD}");
137    /// assert_eq!(range.to_complete().to_string(), "Hello ");
138    /// ```
139    #[inline]
140    #[must_use]
141    pub fn to_complete(mut self) -> Self {
142        self.trim_last_incomplete_char();
143        self
144    }
145
146    /// Returns the range without the last incomplete character and the trimmed length.
147    #[inline]
148    #[must_use]
149    // TODO: Better name?
150    fn to_complete_and_trimmed_len(mut self) -> (Self, usize) {
151        let trimmed = self.trim_last_incomplete_char();
152        (self, trimmed)
153    }
154}
155
156/// Content length and existence.
157impl<'a> CharsRange<'a> {
158    /// Returns the total length.
159    ///
160    /// # Examples
161    ///
162    /// ```
163    /// use str_queue::StrQueue;
164    ///
165    /// let queue = StrQueue::from(b"Hello \xce");
166    /// let range = queue.chars_range(..);
167    /// assert_eq!(range.len(), b"Hello \xce".len());
168    /// ```
169    #[inline]
170    #[must_use]
171    pub fn len(&self) -> usize {
172        self.range.len()
173    }
174
175    /// Returns true if the range is empty.
176    ///
177    /// # Examples
178    ///
179    /// ```
180    /// use str_queue::StrQueue;
181    ///
182    /// let queue = StrQueue::from(b"\xce");
183    /// let range = queue.chars_range(..);
184    /// assert!(!range.is_empty());
185    ///
186    /// assert!(queue.chars_range(0..0).is_empty());
187    /// ```
188    #[inline]
189    #[must_use]
190    pub fn is_empty(&self) -> bool {
191        self.range.is_empty()
192    }
193
194    /// Returns the string length in bytes, excluding incomplete bytes.
195    ///
196    /// # Examples
197    ///
198    /// ```
199    /// use str_queue::StrQueue;
200    ///
201    /// let queue = StrQueue::from(b"hello\xce");
202    /// assert_eq!(queue.chars_range(..).len_complete(), 5);
203    /// ```
204    #[inline]
205    #[must_use]
206    pub fn len_complete(&self) -> usize {
207        self.len() - self.len_incomplete()
208    }
209
210    /// Returns the length of incomplete bytes.
211    ///
212    /// # Examples
213    ///
214    /// ```
215    /// use str_queue::StrQueue;
216    ///
217    /// let queue = StrQueue::from(b"hello\xce");
218    /// assert_eq!(queue.chars_range(..).len_incomplete(), 1);
219    /// ```
220    #[inline]
221    #[must_use]
222    pub fn len_incomplete(&self) -> usize {
223        let former = self.range.former;
224        let latter = self.range.latter;
225        if !latter.is_empty() {
226            if let Some(partial_len) = utf8::last_char_len_in_last_4bytes(latter) {
227                return partial_len.len_incomplete();
228            }
229        }
230
231        // No characters starts from the latter slice.
232        utf8::last_char_len_in_last_4bytes(former)
233            .expect("[validity] the former buffer must be null or start with valid UTF-8 sequence")
234            .len_incomplete()
235    }
236
237    /// Returns true if the chars range contains no complete string.
238    ///
239    /// # Examples
240    ///
241    /// ```
242    /// use str_queue::StrQueue;
243    ///
244    /// let mut queue = StrQueue::new();
245    /// assert!(queue.chars_range(..).is_empty_complete());
246    ///
247    /// queue.push_bytes(b"\xce");
248    /// assert!(queue.chars_range(..).is_empty_complete());
249    ///
250    /// queue.push_bytes(b"\xb1");
251    /// assert!(!queue.chars_range(..).is_empty_complete());
252    /// ```
253    #[inline]
254    #[must_use]
255    pub fn is_empty_complete(&self) -> bool {
256        self.len() == self.len_incomplete()
257    }
258
259    /// Returns true if the chars range is a complete string, i.e. has no
260    /// trailing incomplete character.
261    ///
262    /// # Examples
263    ///
264    /// ```
265    /// use str_queue::StrQueue;
266    ///
267    /// let mut queue = StrQueue::from(b"abc\xce");
268    /// assert!(!queue.chars_range(..).is_complete());
269    /// queue.push_bytes(b"\xb1");
270    /// // Now the string is "abc\u{03B1}".
271    /// assert!(queue.chars_range(..).is_complete());
272    /// ```
273    pub fn is_complete(&self) -> bool {
274        if self.range.latter.is_empty() {
275            // Check only the former.
276            return utf8::last_char_len_in_last_4bytes(self.range.former)
277                .map_or(false, |v| v.is_complete());
278        }
279        if let Some(partial_len) = utf8::last_char_len_in_last_4bytes(self.range.latter) {
280            // Check only the latter.
281            return partial_len.is_complete();
282        }
283
284        // The latter has no beginning of a character.
285        let latter_len = self.range.latter.len();
286        debug_assert!(
287            latter_len < 4,
288            "[consistency] a complete character must start in the last 4 bytes"
289        );
290        debug_assert!(
291            latter_len > 0,
292            "[consistency] must be returned earlily when the latter is empty"
293        );
294        let partial_len = match utf8::last_char_len_in_last_4bytes(self.range.former) {
295            Some(v) => v,
296            None => unreachable!("[consistency] a character start must exist in the last 4 bytes"),
297        };
298        match partial_len.len_missing().cmp(&latter_len) {
299            Ordering::Greater => false,
300            Ordering::Equal => true,
301            Ordering::Less => {
302                unreachable!("[consistency] a character must not be longer than expected")
303            }
304        }
305    }
306}
307
308/// Range and content manipulation.
309impl<'a> CharsRange<'a> {
310    /// Clears the range, removing all elements.
311    ///
312    /// # Examples
313    ///
314    /// ```
315    /// use str_queue::{PartialHandling, StrQueue};
316    ///
317    /// let queue = StrQueue::from(b"Hello \xce");
318    /// let mut range = queue.chars_range(..);
319    /// assert!(!range.is_empty());
320    ///
321    /// range.clear();
322    /// assert!(range.is_empty());
323    /// // Only the range is cleared. The underlying queue does not change.
324    /// assert!(!queue.is_empty());
325    /// ```
326    #[inline]
327    pub fn clear(&mut self) {
328        self.range.clear()
329    }
330
331    /// Trims the last incomplete character, and returns the length of the trimmed bytes.
332    ///
333    /// If the string is complete (i.e. no incomplete character follows), does
334    /// nothing and returns 0.
335    ///
336    /// If you want to get a modified copy instead of modifying `self` itself,
337    /// use [`CharsRange::to_complete`].
338    ///
339    /// # Examples
340    ///
341    /// ```
342    /// use str_queue::{PartialHandling, StrQueue};
343    ///
344    /// let queue = StrQueue::from(b"Hello \xce");
345    /// let mut range = queue.chars_range(..);
346    /// assert_eq!(range.to_string(), "Hello \u{FFFD}");
347    ///
348    /// range.trim_last_incomplete_char();
349    /// assert_eq!(range.to_string(), "Hello ");
350    /// ```
351    pub fn trim_last_incomplete_char(&mut self) -> usize {
352        let former = &mut self.range.former;
353        let latter = &mut self.range.latter;
354
355        if !latter.is_empty() {
356            if let Some(partial_len) = utf8::last_char_len_in_last_4bytes(latter) {
357                let len_incomplete = partial_len.len_incomplete();
358                let valid_up_to = latter.len() - len_incomplete;
359                *latter = &latter[..valid_up_to];
360                return len_incomplete;
361            }
362        }
363
364        // No characters starts from the latter slice.
365        *latter = &latter[..0];
366        // Check for the former slice.
367        let len_incomplete = utf8::last_char_len_in_last_4bytes(former)
368            .expect("[validity] the former buffer must be null or start with valid UTF-8 sequence")
369            .len_incomplete();
370        let valid_up_to = former.len() - len_incomplete;
371        *former = &former[..valid_up_to];
372
373        len_incomplete
374    }
375
376    /// Pops the first character in the range and returns it.
377    ///
378    /// Trailing incomplete character is ignored.
379    ///
380    /// # Examples
381    ///
382    /// ```
383    /// use str_queue::StrQueue;
384    ///
385    /// let queue = StrQueue::from("hello");
386    /// let mut range = queue.chars_range(..);
387    ///
388    /// assert_eq!(range.pop_char(), Some('h'));
389    /// assert_eq!(range.pop_char(), Some('e'));
390    /// assert_eq!(range.pop_char(), Some('l'));
391    /// assert_eq!(range.pop_char(), Some('l'));
392    /// assert_eq!(range.pop_char(), Some('o'));
393    /// assert_eq!(range.pop_char(), None);
394    /// assert!(range.is_empty());
395    /// ```
396    ///
397    /// ```
398    /// use str_queue::StrQueue;
399    ///
400    /// let queue = StrQueue::from(b"a\xf0");
401    /// let mut range = queue.chars_range(..);
402    ///
403    /// assert_eq!(range.pop_char(), Some('a'));
404    /// assert_eq!(range.pop_char(), None);
405    /// assert!(!range.is_empty());
406    /// ```
407    pub fn pop_char(&mut self) -> Option<char> {
408        self.pop_char_raw(false).and_then(Result::ok)
409    }
410
411    /// Pops the first character from the range and returns it.
412    ///
413    /// The trailing incomplete character is replaced with `U+FFFD REPLACEMENT
414    /// CHARACTER`, if available.
415    ///
416    /// # Examples
417    ///
418    /// ```
419    /// use str_queue::StrQueue;
420    ///
421    /// let queue = StrQueue::from(b"abc\xce");
422    /// let mut range = queue.chars_range(..);
423    ///
424    /// assert_eq!(range.pop_char_replaced(), Some('a'));
425    /// assert_eq!(range.pop_char_replaced(), Some('b'));
426    /// assert_eq!(range.pop_char_replaced(), Some('c'));
427    /// assert_eq!(range.pop_char_replaced(), Some('\u{FFFD}'));
428    /// ```
429    pub fn pop_char_replaced(&mut self) -> Option<char> {
430        self.pop_char_raw(true)
431            .map(|res| res.unwrap_or(REPLACEMENT_CHAR))
432    }
433
434    /// Pops the first character from the range and return it.
435    ///
436    /// If the first character is incomplete, `Some(Err(IncompleteCharError))`
437    /// is returned.
438    /// The trailing incomplete character is removed from the range if and only
439    /// if `pop_incomplete` is true.
440    fn pop_char_raw(&mut self, pop_incomplete: bool) -> Option<Result<char, IncompleteCharError>> {
441        if self.range.is_empty() {
442            return None;
443        }
444        match utf8::take_char(self.range.bytes()) {
445            Some((c, len)) => {
446                self.range.trim_start(usize::from(len));
447                Some(Ok(c))
448            }
449            None => {
450                debug_assert!(!self.range.is_empty());
451                // Incomplete character.
452                if pop_incomplete {
453                    self.range.clear();
454                }
455                Some(Err(IncompleteCharError))
456            }
457        }
458    }
459
460    /// Pops the first line in the queue and returns it.
461    ///
462    /// Incomplete lines are ignored.
463    ///
464    /// Note that it is unspecified whether the line will be removed from the queue,
465    /// if the `PoppedLine` value is not dropped while the borrow it holds expires
466    /// (e.g. due to [`core::mem::forget`]).
467    ///
468    /// # Examples
469    ///
470    /// ```
471    /// use str_queue::StrQueue;
472    ///
473    /// // Note that the last "world\r" is not considered as a complete line
474    /// // since the line can be finally "world\r" or "world\r\n".
475    /// let queue = StrQueue::from("Hello\nworld\r\nGoodbye\rworld\r");
476    /// let mut range = queue.chars_range(..);
477    ///
478    /// assert_eq!(range.pop_line().map(|v| v.to_string()).as_deref(), Some("Hello\n"));
479    /// assert_eq!(range.pop_line().map(|v| v.to_string()).as_deref(), Some("world\r\n"));
480    /// assert_eq!(range.pop_line().map(|v| v.to_string()).as_deref(), Some("Goodbye\r"));
481    /// assert_eq!(range.pop_line().map(|v| v.to_string()).as_deref(), None);
482    /// assert_eq!(range, "world\r");
483    /// ```
484    #[inline]
485    pub fn pop_line<'r>(&'r mut self) -> Option<CharsRangePoppedLine<'a, 'r>> {
486        let line_len = self.first_line()?.len();
487        let line_len = NonZeroUsize::new(line_len)
488            .expect("[validity] a complete line must not be empty since it has a line break");
489        Some(CharsRangePoppedLine {
490            range: self,
491            line_len,
492        })
493    }
494
495    /// Pops the first [`Fragment`] from the range and return it.
496    ///
497    /// In other words, takes as much content as possible from the range.
498    ///
499    /// # Examples
500    ///
501    /// ```
502    /// use str_queue::StrQueue;
503    ///
504    /// let queue = StrQueue::from(b"Hello \xce");
505    /// let mut buf = String::new();
506    ///
507    /// let mut range = queue.chars_range(..);
508    /// while let Some(frag) = range.pop_fragment() {
509    ///     buf.push_str(&frag.to_string());
510    /// }
511    ///
512    /// assert_eq!(buf, "Hello \u{FFFD}");
513    /// assert!(range.is_empty());
514    /// ```
515    pub fn pop_fragment(&mut self) -> Option<Fragment<'a>> {
516        if self.range.is_empty() {
517            return None;
518        }
519
520        {
521            let (former_valid, former_incomplete) =
522                utf8::split_incomplete_suffix(self.range.former);
523            if !former_valid.is_empty() {
524                // The former slice has valid UTF-8 sequence as a prefix.
525                self.range.trim_start(former_valid.len());
526                return Some(Fragment::Str(former_valid));
527            }
528            if former_incomplete.is_some() {
529                // The former slice starts with incomplete character.
530                let frag = self
531                    .pop_char_raw(true)
532                    .expect("[consistency] the incomplete bytes are not empty")
533                    .map_or(Fragment::Incomplete, Fragment::Char);
534                return Some(frag);
535            }
536        }
537
538        let (latter_valid, latter_incomplete) = utf8::split_incomplete_suffix(self.range.latter);
539        if !latter_valid.is_empty() {
540            // The latter slice has valid UTF-8 sequence as a prefix since
541            // the range starts inside the latter slice.
542            self.range.trim_start(latter_valid.len());
543            return Some(Fragment::Str(latter_valid));
544        }
545        assert!(
546            latter_incomplete.is_some(),
547            "[consistency] this cannot be empty since the range is not empty here"
548        );
549        // The latter slice starts with (and ends with) the incomplete character.
550        Some(Fragment::Incomplete)
551    }
552}
553
554/// Content access.
555impl<'a> CharsRange<'a> {
556    /// Returns the first character in the range.
557    ///
558    /// # Examples
559    ///
560    /// ```
561    /// use str_queue::StrQueue;
562    ///
563    /// let queue = StrQueue::from("hello");
564    ///
565    /// assert_eq!(queue.first_char(), Some('h'));
566    /// ```
567    #[inline]
568    #[must_use]
569    pub fn first_char(&self) -> Option<char> {
570        let bytes = self
571            .range
572            .former
573            .iter()
574            .chain(self.range.latter.iter())
575            .take(4)
576            .copied();
577        utf8::take_char(bytes).map(|(c, _len)| c)
578    }
579
580    /// Returns the subrange of the first line, including the line break.
581    ///
582    /// Returns `Some(range)` if the range contains a complete line, which
583    /// won't be changed if more contents are appended.
584    /// Returns `None` if the range contains only an incomplete line,
585    /// which will be changed if more contents are appended.
586    ///
587    /// # Examples
588    ///
589    /// ```
590    /// use str_queue::StrQueue;
591    ///
592    /// let mut queue = StrQueue::from(b"Hello \xce");
593    /// assert_eq!(
594    ///     queue.chars_range(..).first_line().map(|r| r.to_string()),
595    ///     None
596    /// );
597    ///
598    /// queue.push_bytes(b"\xb1\r");
599    /// // The line is still considered incomplete since the line ending can be `\r\n`.
600    /// assert_eq!(
601    ///     queue.chars_range(..).first_line().map(|r| r.to_string()),
602    ///     None
603    /// );
604    ///
605    /// queue.push_bytes(b"\nhello");
606    /// assert_eq!(
607    ///     queue.chars_range(..).first_line().map(|r| r.to_string()),
608    ///     Some("Hello \u{03B1}\r\n".to_owned())
609    /// );
610    /// ```
611    ///
612    /// ```
613    /// use str_queue::{PartialHandling, StrQueue};
614    ///
615    /// let queue = StrQueue::from(b"Hello\n");
616    /// assert_eq!(
617    ///     queue.chars_range(..).first_line().map(|r| r.to_string()),
618    ///     Some("Hello\n".to_owned())
619    /// );
620    /// ```
621    pub fn first_line(&self) -> Option<CharsRange<'a>> {
622        self.next_line_position().map(|pos| self.range(..pos.get()))
623    }
624
625    /// Returns the position where the next line starts.
626    #[must_use]
627    fn next_line_position(&self) -> Option<NonZeroUsize> {
628        let first_newline = self.range.position2(b'\n', b'\r')?;
629        debug_assert!(
630            first_newline < usize::MAX,
631            "the string length won't be `usize::MAX` \
632                 since other objects (including self) may exist on memory"
633        );
634        if self.range.former[first_newline] == b'\n' {
635            return NonZeroUsize::new(first_newline + 1);
636        }
637        assert_eq!(self.range.former[first_newline], b'\r');
638
639        // The string ending with `\r` is considered incomplete line,
640        // since it is unsure which is used as the line ending, `\r` or `\r\n`.
641        let next = self.range.get_byte(first_newline + 1)?;
642        if next == b'\n' {
643            debug_assert!(
644                first_newline + 1 < usize::MAX,
645                "the string length won't be `usize::MAX` \
646                 since other objects (including self) may exist on memory"
647            );
648            NonZeroUsize::new(first_newline + 2)
649        } else {
650            NonZeroUsize::new(first_newline + 1)
651        }
652    }
653}
654
655/// Iterators.
656impl<'a> CharsRange<'a> {
657    /// Returns an iterator of `char`s.
658    ///
659    /// Incomplete characters are emitted as `U+FFFD REPLACEMENT CHARACTER`.
660    /// If you want to ignore them, use [`CharsRange::to_complete`] or
661    /// [`CharsRange::trim_last_incomplete_char`] before creating the iterator.
662    ///
663    /// # Examples
664    ///
665    /// ```
666    /// use str_queue::{PartialHandling, StrQueue};
667    ///
668    /// let queue = StrQueue::from(b"alpha->\xce");
669    /// let range = queue.chars_range(..);
670    ///
671    /// // The trailing incomplete character is replaced with U+FFFD.
672    /// assert_eq!(
673    ///     range.chars().collect::<String>(),
674    ///     "alpha->\u{FFFD}"
675    /// );
676    /// ```
677    #[inline]
678    #[must_use]
679    pub fn chars(&self) -> Chars<'_> {
680        Chars::from_range(*self)
681    }
682
683    /// Returns an iterator of content fragments.
684    ///
685    /// # Examples
686    ///
687    /// The code below are redundant since they are intended to show how to use [`Fragment`].
688    /// To simply create a string from the queue, use [`StrQueue::display`] method.
689    ///
690    /// ```
691    /// use str_queue::{Fragment, StrQueue};
692    ///
693    /// // `\xce\xb1` is `\u{03B1}`.
694    /// let queue = StrQueue::from(b"hello \xce\xb1");
695    /// let range = queue.chars_range(3..7);
696    ///
697    /// let mut buf = String::new();
698    /// for frag in range.fragments() {
699    ///     match frag {
700    ///         Fragment::Str(s) => buf.push_str(s),
701    ///         Fragment::Char(c) => buf.push(c),
702    ///         Fragment::Incomplete => buf.push_str("<<incomplete>>"),
703    ///     }
704    /// }
705    /// assert_eq!(buf, "lo <<incomplete>>");
706    /// ```
707    #[inline]
708    #[must_use]
709    pub fn fragments(&self) -> Fragments<'_> {
710        Fragments::from_range(*self)
711    }
712}
713
714/// Conversion.
715impl<'a> CharsRange<'a> {
716    /// Returns the bytes range.
717    #[inline]
718    #[must_use]
719    pub fn to_bytes_range(&self) -> BytesRange<'a> {
720        (*self).into()
721    }
722}
723
724/// Comparison.
725impl CharsRange<'_> {
726    /// Compares the two chars ranges.
727    ///
728    /// This comparson is arawe of the existence of the last incomplete
729    /// characters, but does not aware of its value.
730    /// If you care about the value of the incomplete characters, you should use
731    /// bytes comparison.
732    ///
733    /// If the range has the incomplete character, it is treated as a character
734    /// which is smaller than any other characters.
735    /// In other words, the comparison result can be thought as
736    /// `(lhs.complete(), !lhs.is_complete()).cmp(&(rhs.complete(), !rhs.is_complete()))`.
737    ///
738    /// # Examples
739    ///
740    /// ```
741    /// use str_queue::{PartialHandling, StrQueue};
742    /// use core::cmp::Ordering;
743    ///
744    /// let queue_ce = StrQueue::from(b"Hello\xce");
745    /// let range_ce = queue_ce.chars_range(..);
746    /// let queue_f0 = StrQueue::from(b"Hello\xf0");
747    /// let range_f0 = queue_f0.chars_range(..);
748    ///
749    /// // Bytes for incomplete characters are considered the same.
750    /// assert_eq!(range_ce, range_f0);
751    /// assert_eq!(range_ce.cmp(&range_f0), Ordering::Equal);
752    /// // To distinguish incomplete characters, use bytes range.
753    /// assert_ne!(range_ce.to_bytes_range(), range_f0.to_bytes_range());
754    /// assert_eq!(
755    ///     range_ce.to_bytes_range().cmp(&range_f0.to_bytes_range()),
756    ///     Ordering::Less
757    /// );
758    /// ```
759    ///
760    /// ```
761    /// use str_queue::{PartialHandling, StrQueue};
762    /// use core::cmp::Ordering;
763    ///
764    /// let queue_ce = StrQueue::from(b"Hello\xce");
765    /// let range_ce = queue_ce.chars_range(..);
766    ///
767    /// let queue_none = StrQueue::from(b"Hello");
768    /// let range_none = queue_none.chars_range(..);
769    /// assert_ne!(range_ce, range_none);
770    /// assert_eq!(range_ce.partial_cmp(&range_none), Some(Ordering::Greater));
771    ///
772    /// let queue_00 = StrQueue::from(b"Hello\x00");
773    /// let range_00 = queue_00.chars_range(..);
774    /// assert_ne!(range_ce, range_00);
775    /// // `\xce` is incomplete, so it is considered smaller than `\x00`.
776    /// // Note that `\x00` is a valid ASCII character.
777    /// assert_eq!(range_ce.partial_cmp(&range_00), Some(Ordering::Less));
778    ///
779    /// let queue_ufffd = StrQueue::from("Hello\u{FFFD}");
780    /// let range_ufffd = queue_ufffd.chars_range(..);
781    /// assert_ne!(range_ce, range_ufffd);
782    /// // The incomplete character (which consists of `\xce`) is converted to
783    /// // `\u{FFFD}` when displayed, but it is not considered to be the same
784    /// // as a valid Unicode character `\u{FFFD}`.
785    /// assert_eq!(range_ce.partial_cmp(&range_ufffd), Some(Ordering::Less));
786    /// ```
787    fn cmp_self(&self, rhs: &Self) -> Ordering {
788        let self_has_incomplete = !self.is_complete();
789        let rhs_has_incomplete = !rhs.is_complete();
790        self.to_complete()
791            .range
792            .cmp_self(&rhs.to_complete().range)
793            .then_with(|| self_has_incomplete.cmp(&rhs_has_incomplete))
794    }
795
796    /// Compares the chars range and a string slice.
797    ///
798    /// If the range has the incomplete character, it is treated as a character
799    /// which is smaller than any other characters.
800    /// In other words, the comparison result can be thought as
801    /// `(range.complete(), !range.is_complete()).cmp(&(rhs, false))`.
802    /// The complete part differ from the rhs string slice, that result is
803    /// returned regardless of the incomplete character.
804    ///
805    /// # Examples
806    ///
807    /// ```
808    /// use str_queue::{PartialHandling, StrQueue};
809    /// use core::cmp::Ordering;
810    ///
811    /// let queue_00 = StrQueue::from(b"Hello\x00");
812    /// let range_00 = queue_00.chars_range(..);
813    /// let queue_ce = StrQueue::from(b"Hello\xce");
814    /// let range_ce = queue_ce.chars_range(..);
815    ///
816    /// assert_eq!(range_00, "Hello\u{0}");
817    /// assert_eq!(range_00.partial_cmp("Hello\u{0}"), Some(Ordering::Equal));
818    ///
819    /// assert_eq!(range_ce.partial_cmp("Hello"), Some(Ordering::Greater));
820    /// // `\xce` is incomplete, so it is considered smaller than `\x00`.
821    /// // Note that `\x00` is a valid ASCII character.
822    /// assert_eq!(range_ce.partial_cmp("Hello\u{0}"), Some(Ordering::Less));
823    /// // The incomplete character (which consists of `\xce`) is converted to
824    /// // `\u{FFFD}` when displayed, but it is not considered to be the same
825    /// // as a valid Unicode character `\u{FFFD}`.
826    /// assert_eq!(range_ce.partial_cmp("Hello\u{FFFD}"), Some(Ordering::Less));
827    /// ```
828    fn cmp_str(&self, rhs: &str) -> Ordering {
829        let (complete, trimmed_len) = self.to_complete_and_trimmed_len();
830        let fallback = || {
831            if trimmed_len == 0 {
832                Ordering::Equal
833            } else {
834                Ordering::Greater
835            }
836        };
837
838        let former_len = complete.range.former.len();
839        let rhs = rhs.as_bytes();
840        let rhs_len = rhs.len();
841
842        if former_len > rhs_len {
843            complete.range.former.cmp(rhs).then_with(fallback)
844        } else {
845            complete
846                .range
847                .former
848                .cmp(&rhs[..former_len])
849                .then_with(|| complete.range.latter.cmp(&rhs[former_len..]))
850                .then_with(fallback)
851        }
852    }
853}
854
855impl fmt::Display for CharsRange<'_> {
856    #[inline]
857    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
858        Fragments::from(*self).fmt(f)
859    }
860}
861
862impl<'a> From<CharsRange<'a>> for BytesRange<'a> {
863    #[inline]
864    fn from(v: CharsRange<'a>) -> Self {
865        v.range
866    }
867}
868
869impl PartialEq for CharsRange<'_> {
870    /// Compares the two chars ranges and returns true if they are equal.
871    ///
872    /// This comparson is arawe of the existence of the last incomplete
873    /// characters, but does not aware of its value.
874    /// If you care about the value of the incomplete characters, you should use
875    /// bytes comparison.
876    ///
877    /// # Examples
878    ///
879    /// ```
880    /// use str_queue::{PartialHandling, StrQueue};
881    /// use core::cmp::Ordering;
882    ///
883    /// let queue1 = StrQueue::from(b"Hello\xce");
884    /// let range1 = queue1.chars_range(..);
885    /// let queue2 = StrQueue::from(b"Hello\xf0");
886    /// let range2 = queue2.chars_range(..);
887    ///
888    /// assert_eq!(range1, range2);
889    /// assert_ne!(range1.to_bytes_range(), range2.to_bytes_range());
890    /// ```
891    #[inline]
892    fn eq(&self, other: &Self) -> bool {
893        // Return earlily if lengths are not the same.
894        (self.len() == other.len()) && self.cmp_self(other).is_eq()
895    }
896}
897
898impl PartialOrd for CharsRange<'_> {
899    /// Compares the two chars ranges.
900    ///
901    /// This comparson is arawe of the existence of the last incomplete
902    /// characters, but does not aware of its value.
903    /// If you care about the value of the incomplete characters, you should use
904    /// bytes comparison.
905    ///
906    /// If the range has the incomplete character, it is treated as a character
907    /// which is smaller than any other characters.
908    /// In other words, the comparison result can be thought as
909    /// `(lhs.complete(), !lhs.is_complete()).cmp(&(rhs.complete(), !rhs.is_complete()))`.
910    ///
911    /// # Examples
912    ///
913    /// ```
914    /// use str_queue::{PartialHandling, StrQueue};
915    /// use core::cmp::Ordering;
916    ///
917    /// let queue_ce = StrQueue::from(b"Hello\xce");
918    /// let range_ce = queue_ce.chars_range(..);
919    /// let queue_f0 = StrQueue::from(b"Hello\xf0");
920    /// let range_f0 = queue_f0.chars_range(..);
921    ///
922    /// // Bytes for incomplete characters are considered the same.
923    /// assert_eq!(range_ce, range_f0);
924    /// assert_eq!(range_ce.cmp(&range_f0), Ordering::Equal);
925    /// // To distinguish incomplete characters, use bytes range.
926    /// assert_ne!(range_ce.to_bytes_range(), range_f0.to_bytes_range());
927    /// assert_eq!(
928    ///     range_ce.to_bytes_range().cmp(&range_f0.to_bytes_range()),
929    ///     Ordering::Less
930    /// );
931    /// ```
932    ///
933    /// ```
934    /// use str_queue::{PartialHandling, StrQueue};
935    /// use core::cmp::Ordering;
936    ///
937    /// let queue_ce = StrQueue::from(b"Hello\xce");
938    /// let range_ce = queue_ce.chars_range(..);
939    ///
940    /// let queue_none = StrQueue::from(b"Hello");
941    /// let range_none = queue_none.chars_range(..);
942    /// assert_ne!(range_ce, range_none);
943    /// assert_eq!(range_ce.partial_cmp(&range_none), Some(Ordering::Greater));
944    ///
945    /// let queue_00 = StrQueue::from(b"Hello\x00");
946    /// let range_00 = queue_00.chars_range(..);
947    /// assert_ne!(range_ce, range_00);
948    /// // `\xce` is incomplete, so it is considered smaller than `\x00`.
949    /// // Note that `\x00` is a valid ASCII character.
950    /// assert_eq!(range_ce.partial_cmp(&range_00), Some(Ordering::Less));
951    ///
952    /// let queue_ufffd = StrQueue::from("Hello\u{FFFD}");
953    /// let range_ufffd = queue_ufffd.chars_range(..);
954    /// assert_ne!(range_ce, range_ufffd);
955    /// // The incomplete character (which consists of `\xce`) is converted to
956    /// // `\u{FFFD}` when displayed, but it is not considered to be the same
957    /// // as a valid Unicode character `\u{FFFD}`.
958    /// assert_eq!(range_ce.partial_cmp(&range_ufffd), Some(Ordering::Less));
959    /// ```
960    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
961        Some(self.cmp_self(rhs))
962    }
963}
964
965impl Ord for CharsRange<'_> {
966    ///
967    /// This comparson is arawe of the existence of the last incomplete
968    /// characters, but does not aware of its value.
969    /// If you care about the value of the incomplete characters, you should use
970    /// bytes comparison.
971    ///
972    /// If the range has the incomplete character, it is treated as a character
973    /// which is smaller than any other characters.
974    /// In other words, the comparison result can be thought as
975    /// `(lhs.complete(), !lhs.is_complete()).cmp(&(rhs.complete(), !rhs.is_complete()))`.
976    ///
977    /// # Examples
978    ///
979    /// ```
980    /// use str_queue::{PartialHandling, StrQueue};
981    /// use core::cmp::Ordering;
982    ///
983    /// let queue_ce = StrQueue::from(b"Hello\xce");
984    /// let range_ce = queue_ce.chars_range(..);
985    /// let queue_f0 = StrQueue::from(b"Hello\xf0");
986    /// let range_f0 = queue_f0.chars_range(..);
987    ///
988    /// // Bytes for incomplete characters are considered the same.
989    /// assert_eq!(range_ce, range_f0);
990    /// assert_eq!(range_ce.cmp(&range_f0), Ordering::Equal);
991    /// // To distinguish incomplete characters, use bytes range.
992    /// assert_ne!(range_ce.to_bytes_range(), range_f0.to_bytes_range());
993    /// assert_eq!(
994    ///     range_ce.to_bytes_range().cmp(&range_f0.to_bytes_range()),
995    ///     Ordering::Less
996    /// );
997    /// ```
998    ///
999    /// ```
1000    /// use str_queue::{PartialHandling, StrQueue};
1001    /// use core::cmp::Ordering;
1002    ///
1003    /// let queue_ce = StrQueue::from(b"Hello\xce");
1004    /// let range_ce = queue_ce.chars_range(..);
1005    ///
1006    /// let queue_none = StrQueue::from(b"Hello");
1007    /// let range_none = queue_none.chars_range(..);
1008    /// assert_ne!(range_ce, range_none);
1009    /// assert_eq!(range_ce.partial_cmp(&range_none), Some(Ordering::Greater));
1010    ///
1011    /// let queue_00 = StrQueue::from(b"Hello\x00");
1012    /// let range_00 = queue_00.chars_range(..);
1013    /// assert_ne!(range_ce, range_00);
1014    /// // `\xce` is incomplete, so it is considered smaller than `\x00`.
1015    /// // Note that `\x00` is a valid ASCII character.
1016    /// assert_eq!(range_ce.partial_cmp(&range_00), Some(Ordering::Less));
1017    ///
1018    /// let queue_ufffd = StrQueue::from("Hello\u{FFFD}");
1019    /// let range_ufffd = queue_ufffd.chars_range(..);
1020    /// assert_ne!(range_ce, range_ufffd);
1021    /// // The incomplete character (which consists of `\xce`) is converted to
1022    /// // `\u{FFFD}` when displayed, but it is not considered to be the same
1023    /// // as a valid Unicode character `\u{FFFD}`.
1024    /// assert_eq!(range_ce.partial_cmp(&range_ufffd), Some(Ordering::Less));
1025    /// ```
1026    fn cmp(&self, rhs: &Self) -> Ordering {
1027        self.cmp_self(rhs)
1028    }
1029}
1030
1031impl PartialEq<str> for CharsRange<'_> {
1032    #[inline]
1033    fn eq(&self, other: &str) -> bool {
1034        // Return earlily if lengths are not the same.
1035        (self.len() == other.len()) && self.cmp_str(other).is_eq()
1036    }
1037}
1038
1039impl PartialOrd<str> for CharsRange<'_> {
1040    /// Compares the chars range and a string slice.
1041    ///
1042    /// If the range has the incomplete character, it is treated as a character
1043    /// which is smaller than any other characters.
1044    /// In other words, the comparison result can be thought as
1045    /// `(range.complete(), !range.is_complete()).cmp(&(rhs, false))`.
1046    /// The complete part differ from the rhs string slice, that result is
1047    /// returned regardless of the incomplete character.
1048    ///
1049    /// # Examples
1050    ///
1051    /// ```
1052    /// use str_queue::{PartialHandling, StrQueue};
1053    /// use core::cmp::Ordering;
1054    ///
1055    /// let queue_00 = StrQueue::from(b"Hello\x00");
1056    /// let range_00 = queue_00.chars_range(..);
1057    /// let queue_ce = StrQueue::from(b"Hello\xce");
1058    /// let range_ce = queue_ce.chars_range(..);
1059    ///
1060    /// assert_eq!(range_00, "Hello\u{0}");
1061    /// assert_eq!(range_00.partial_cmp("Hello\u{0}"), Some(Ordering::Equal));
1062    ///
1063    /// assert_eq!(range_ce.partial_cmp("Hello"), Some(Ordering::Greater));
1064    /// // `\xce` is incomplete, so it is considered smaller than `\x00`.
1065    /// // Note that `\x00` is a valid ASCII character.
1066    /// assert_eq!(range_ce.partial_cmp("Hello\u{0}"), Some(Ordering::Less));
1067    /// // The incomplete character (which consists of `\xce`) is converted to
1068    /// // `\u{FFFD}` when displayed, but it is not considered to be the same
1069    /// // as a valid Unicode character `\u{FFFD}`.
1070    /// assert_eq!(range_ce.partial_cmp("Hello\u{FFFD}"), Some(Ordering::Less));
1071    /// ```
1072    #[inline]
1073    fn partial_cmp(&self, rhs: &str) -> Option<Ordering> {
1074        Some(self.cmp_str(rhs))
1075    }
1076}
1077
1078impl PartialEq<CharsRange<'_>> for str {
1079    #[inline]
1080    fn eq(&self, other: &CharsRange<'_>) -> bool {
1081        other.eq(self)
1082    }
1083}
1084
1085impl PartialOrd<CharsRange<'_>> for str {
1086    #[inline]
1087    fn partial_cmp(&self, rhs: &CharsRange<'_>) -> Option<Ordering> {
1088        rhs.partial_cmp(self).map(Ordering::reverse)
1089    }
1090}
1091
1092impl PartialEq<&str> for CharsRange<'_> {
1093    #[inline]
1094    fn eq(&self, other: &&str) -> bool {
1095        self.eq(*other)
1096    }
1097}
1098
1099impl PartialOrd<&str> for CharsRange<'_> {
1100    #[inline]
1101    fn partial_cmp(&self, rhs: &&str) -> Option<Ordering> {
1102        self.partial_cmp(*rhs)
1103    }
1104}
1105
1106impl PartialEq<CharsRange<'_>> for &str {
1107    #[inline]
1108    fn eq(&self, other: &CharsRange<'_>) -> bool {
1109        other.eq(*self)
1110    }
1111}
1112
1113impl PartialOrd<CharsRange<'_>> for &str {
1114    #[inline]
1115    fn partial_cmp(&self, rhs: &CharsRange<'_>) -> Option<Ordering> {
1116        rhs.partial_cmp(*self).map(Ordering::reverse)
1117    }
1118}
1119
1120/// A line popped from [`CharsRange`] using [`pop_line`][`CharsRange::pop_line`] method.
1121///
1122/// Note that this may pop a line from `CharsRange`, but `StrQueue` behind the
1123/// range won't be affected.
1124///
1125/// Also note that it is unspecified whether the line will be removed from the
1126/// queue, if the `CharsRangePoppedLine` value is not dropped while the borrow
1127/// it holds expires (e.g. due to [`core::mem::forget`]).
1128#[derive(Debug)]
1129pub struct CharsRangePoppedLine<'a, 'r> {
1130    /// Range.
1131    range: &'r mut CharsRange<'a>,
1132    /// Line length.
1133    ///
1134    /// A complete line cannot be empty since it has a line break.
1135    line_len: NonZeroUsize,
1136}
1137
1138impl<'a, 'r> CharsRangePoppedLine<'a, 'r> {
1139    /// Returns the chars range for the line.
1140    #[inline]
1141    #[must_use]
1142    pub fn to_chars_range(&self) -> CharsRange<'a> {
1143        self.range.range(..self.line_len.get())
1144    }
1145
1146    /// Returns the bytes range for the line.
1147    #[inline]
1148    #[must_use]
1149    pub fn to_bytes_range(&self) -> BytesRange<'_> {
1150        self.range.to_bytes_range().range(..self.line_len.get())
1151    }
1152
1153    /// Returns the length of the line.
1154    #[inline]
1155    #[must_use]
1156    pub fn len(&self) -> usize {
1157        self.line_len.get()
1158    }
1159
1160    /// Returns whether the line is empty, i.e. **always returns false**.
1161    ///
1162    /// A complete line to be removed cannot be empty since it has a line break.
1163    #[inline]
1164    #[must_use]
1165    pub const fn is_empty(&self) -> bool {
1166        false
1167    }
1168}
1169
1170impl fmt::Display for CharsRangePoppedLine<'_, '_> {
1171    #[inline]
1172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1173        self.to_chars_range().fmt(f)
1174    }
1175}
1176
1177impl core::ops::Drop for CharsRangePoppedLine<'_, '_> {
1178    #[inline]
1179    fn drop(&mut self) {
1180        *self.range = self.range.range(self.line_len.get()..);
1181    }
1182}
1183
1184impl PartialEq for CharsRangePoppedLine<'_, '_> {
1185    #[inline]
1186    fn eq(&self, other: &CharsRangePoppedLine<'_, '_>) -> bool {
1187        self.to_bytes_range().eq(&other.to_bytes_range())
1188    }
1189}
1190
1191impl Eq for CharsRangePoppedLine<'_, '_> {}
1192
1193impl PartialOrd for CharsRangePoppedLine<'_, '_> {
1194    #[inline]
1195    fn partial_cmp(&self, rhs: &CharsRangePoppedLine<'_, '_>) -> Option<Ordering> {
1196        self.to_bytes_range().partial_cmp(&rhs.to_bytes_range())
1197    }
1198}
1199
1200impl Ord for CharsRangePoppedLine<'_, '_> {
1201    #[inline]
1202    fn cmp(&self, rhs: &CharsRangePoppedLine<'_, '_>) -> Ordering {
1203        self.to_bytes_range().cmp(&rhs.to_bytes_range())
1204    }
1205}
1206
1207impl PartialEq<str> for CharsRangePoppedLine<'_, '_> {
1208    #[inline]
1209    fn eq(&self, other: &str) -> bool {
1210        self.to_bytes_range().eq(other.as_bytes())
1211    }
1212}
1213
1214impl PartialOrd<str> for CharsRangePoppedLine<'_, '_> {
1215    #[inline]
1216    fn partial_cmp(&self, rhs: &str) -> Option<Ordering> {
1217        self.to_bytes_range().partial_cmp(rhs.as_bytes())
1218    }
1219}
1220
1221impl PartialEq<CharsRangePoppedLine<'_, '_>> for str {
1222    #[inline]
1223    fn eq(&self, other: &CharsRangePoppedLine<'_, '_>) -> bool {
1224        other.to_bytes_range().eq(self.as_bytes())
1225    }
1226}
1227
1228impl PartialOrd<CharsRangePoppedLine<'_, '_>> for str {
1229    #[inline]
1230    fn partial_cmp(&self, rhs: &CharsRangePoppedLine<'_, '_>) -> Option<Ordering> {
1231        rhs.to_bytes_range()
1232            .partial_cmp(self.as_bytes())
1233            .map(Ordering::reverse)
1234    }
1235}
1236
1237impl PartialEq<&str> for CharsRangePoppedLine<'_, '_> {
1238    #[inline]
1239    fn eq(&self, other: &&str) -> bool {
1240        self.eq(*other)
1241    }
1242}
1243
1244impl PartialOrd<&str> for CharsRangePoppedLine<'_, '_> {
1245    #[inline]
1246    fn partial_cmp(&self, rhs: &&str) -> Option<Ordering> {
1247        self.partial_cmp(*rhs)
1248    }
1249}
1250
1251impl PartialEq<CharsRangePoppedLine<'_, '_>> for &str {
1252    #[inline]
1253    fn eq(&self, other: &CharsRangePoppedLine<'_, '_>) -> bool {
1254        other.eq(*self)
1255    }
1256}
1257
1258impl PartialOrd<CharsRangePoppedLine<'_, '_>> for &str {
1259    #[inline]
1260    fn partial_cmp(&self, rhs: &CharsRangePoppedLine<'_, '_>) -> Option<Ordering> {
1261        rhs.partial_cmp(*self).map(Ordering::reverse)
1262    }
1263}