spinoso_string/enc/
codepoints.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use core::iter::FusedIterator;

use super::{
    ascii::{self, AsciiString},
    binary::{self, BinaryString},
    utf8::{self, Utf8String},
};
use crate::CodepointsError;

#[derive(Default, Debug, Clone)]
#[must_use = "this `Codepoint` is an `Iterator`, which should be consumed if constructed"]
pub struct Codepoints<'a>(State<'a>);

impl<'a> From<&'a AsciiString> for Codepoints<'a> {
    fn from(value: &'a AsciiString) -> Self {
        Self(State::Ascii(ascii::Codepoints::new(value)))
    }
}

impl<'a> From<&'a BinaryString> for Codepoints<'a> {
    fn from(value: &'a BinaryString) -> Self {
        Self(State::Binary(binary::Codepoints::new(value)))
    }
}
impl<'a> TryFrom<&'a Utf8String> for Codepoints<'a> {
    type Error = CodepointsError;

    fn try_from(s: &'a Utf8String) -> Result<Self, Self::Error> {
        utf8::Codepoints::try_from(s.as_utf8_str()).map(|v| Self(State::Utf8(v)))
    }
}

#[derive(Debug, Clone)]
enum State<'a> {
    Ascii(ascii::Codepoints<'a>),
    Binary(binary::Codepoints<'a>),
    Utf8(utf8::Codepoints<'a>),
}

impl Default for State<'_> {
    fn default() -> Self {
        Self::Ascii(ascii::Codepoints::default())
    }
}

impl Iterator for Codepoints<'_> {
    type Item = u32;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        match self {
            Self(State::Ascii(iter)) => iter.next(),
            Self(State::Binary(iter)) => iter.next(),
            Self(State::Utf8(iter)) => iter.next().map(u32::from),
        }
    }
}

impl FusedIterator for Codepoints<'_> {}