str-queue 0.0.1

Queue for a string
Documentation
//! Fragments iterator.

use core::fmt::{self, Write as _};
use core::ops::RangeBounds;

use crate::range::CharsRange;
use crate::utf8::REPLACEMENT_CHAR_STR;
use crate::{PartialHandling, StrQueue};

/// Content fragment of [`StrQueue`], emitted by [`Fragments`] iterator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Fragment<'a> {
    /// String slice.
    Str(&'a str),
    /// A character.
    Char(char),
    /// Incomplete bytes.
    ///
    /// This must be the last fragment if available.
    Incomplete,
}

impl fmt::Display for Fragment<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Self::Str(s) => f.write_str(s),
            Self::Char(c) => f.write_char(c),
            Self::Incomplete => f.write_str(REPLACEMENT_CHAR_STR),
        }
    }
}

/// Iterator of content fragments of [`StrQueue`], created by [`StrQueue::fragments`].
#[derive(Debug, Clone)]
pub struct Fragments<'a> {
    /// Buffer range of the queue.
    range: CharsRange<'a>,
}

impl<'a> Fragments<'a> {
    /// Creates a new fragments iterator.
    #[inline]
    #[must_use]
    pub(crate) fn new<R>(queue: &'a StrQueue, range: R, partial_handling: PartialHandling) -> Self
    where
        R: RangeBounds<usize>,
    {
        let mut range = queue.chars_range(range);
        if partial_handling.is_ignore() {
            range.trim_last_incomplete_char();
        }
        Self { range }
    }

    /// Creates a new `CharsRange` from the chars range.
    #[inline]
    #[must_use]
    pub(crate) fn from_range(range: CharsRange<'a>) -> Self {
        Self { range }
    }
}

impl<'a> Iterator for Fragments<'a> {
    type Item = Fragment<'a>;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.range.pop_fragment()
    }
}

impl fmt::Display for Fragments<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.clone().try_for_each(|frag| frag.fmt(f))
    }
}

impl<'a> From<CharsRange<'a>> for Fragments<'a> {
    #[inline]
    fn from(range: CharsRange<'a>) -> Self {
        Self { range }
    }
}