str_queue/iter/
fragments.rs

1//! Fragments iterator.
2
3use core::fmt::{self, Write as _};
4use core::ops::RangeBounds;
5
6use crate::range::CharsRange;
7use crate::utf8::REPLACEMENT_CHAR_STR;
8use crate::{PartialHandling, StrQueue};
9
10/// Content fragment of [`StrQueue`], emitted by [`Fragments`] iterator.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub enum Fragment<'a> {
13    /// String slice.
14    Str(&'a str),
15    /// A character.
16    Char(char),
17    /// Incomplete bytes.
18    ///
19    /// This must be the last fragment if available.
20    Incomplete,
21}
22
23impl fmt::Display for Fragment<'_> {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        match *self {
26            Self::Str(s) => f.write_str(s),
27            Self::Char(c) => f.write_char(c),
28            Self::Incomplete => f.write_str(REPLACEMENT_CHAR_STR),
29        }
30    }
31}
32
33/// Iterator of content fragments of [`StrQueue`], created by [`StrQueue::fragments`].
34#[derive(Debug, Clone)]
35pub struct Fragments<'a> {
36    /// Buffer range of the queue.
37    range: CharsRange<'a>,
38}
39
40impl<'a> Fragments<'a> {
41    /// Creates a new fragments iterator.
42    #[inline]
43    #[must_use]
44    pub(crate) fn new<R>(queue: &'a StrQueue, range: R, partial_handling: PartialHandling) -> Self
45    where
46        R: RangeBounds<usize>,
47    {
48        let mut range = queue.chars_range(range);
49        if partial_handling.is_ignore() {
50            range.trim_last_incomplete_char();
51        }
52        Self { range }
53    }
54
55    /// Creates a new `CharsRange` from the chars range.
56    #[inline]
57    #[must_use]
58    pub(crate) fn from_range(range: CharsRange<'a>) -> Self {
59        Self { range }
60    }
61}
62
63impl<'a> Iterator for Fragments<'a> {
64    type Item = Fragment<'a>;
65
66    #[inline]
67    fn next(&mut self) -> Option<Self::Item> {
68        self.range.pop_fragment()
69    }
70}
71
72impl fmt::Display for Fragments<'_> {
73    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74        self.clone().try_for_each(|frag| frag.fmt(f))
75    }
76}
77
78impl<'a> From<CharsRange<'a>> for Fragments<'a> {
79    #[inline]
80    fn from(range: CharsRange<'a>) -> Self {
81        Self { range }
82    }
83}