Skip to main content

object_rainbow/impls/
char.rs

1use typenum::{B0, B1, U1};
2
3use crate::{enumkind::UsizeTag, *};
4
5impl ToOutput for char {
6    fn to_output(&self, output: &mut impl Output) {
7        if output.is_real() {
8            let mut buf = [0; 4];
9            self.encode_utf8(&mut buf).to_output(output);
10        }
11    }
12}
13
14impl<I: ParseInput> Parse<I> for char {
15    fn parse(input: I) -> crate::Result<Self> {
16        Self::parse_as_inline(input)
17    }
18}
19
20impl<I: ParseInput> ParseInline<I> for char {
21    fn parse_inline(input: &mut I) -> crate::Result<Self> {
22        let c0 = input.parse_inline::<u8>()?;
23        if c0 & 0b11000000 != 0b11000000 {
24            let c = str::from_utf8(&[c0])
25                .map_err(crate::Error::parse)?
26                .chars()
27                .next()
28                .expect("this string is not empty");
29            return Ok(c);
30        }
31        let c1 = input.parse_inline::<u8>()?;
32        if c0 & 0b00100000 == 0 {
33            let c = str::from_utf8(&[c0, c1])
34                .map_err(crate::Error::parse)?
35                .chars()
36                .next()
37                .expect("this string is not empty");
38            return Ok(c);
39        }
40        let c2 = input.parse_inline::<u8>()?;
41        if c0 & 0b00010000 == 0 {
42            let c = str::from_utf8(&[c0, c1, c2])
43                .map_err(crate::Error::parse)?
44                .chars()
45                .next()
46                .expect("this string is not empty");
47            return Ok(c);
48        }
49        let c3 = input.parse_inline::<u8>()?;
50        let c = str::from_utf8(&[c0, c1, c2, c3])
51            .map_err(crate::Error::parse)?
52            .chars()
53            .next()
54            .expect("this string is not empty");
55        Ok(c)
56    }
57}
58
59impl InlineOutput for char {}
60impl Tagged for char {}
61impl ListHashes for char {}
62impl Topological for char {}
63
64pub struct CharNiche;
65pub struct CharNicheNext;
66
67impl Niche for CharNiche {
68    type NeedsTag = B0;
69    type Cut = B1;
70    type N = U1;
71    fn niche() -> GenericArray<u8, Self::N> {
72        [0xffu8].into()
73    }
74    type Next = CharNicheNext;
75}
76
77impl MaybeHasNiche for char {
78    type MnArray = SomeNiche<CharNiche>;
79}
80
81impl ByteOrd for char {
82    fn bytes_cmp(&self, other: &Self) -> Ordering {
83        self.cmp(other)
84    }
85}
86
87impl SignificantLength for char {}
88
89impl UsizeTag for char {
90    fn from_usize(n: usize) -> Self {
91        Self::from_u32(n.try_into().unwrap()).unwrap()
92    }
93
94    fn to_usize(&self) -> usize {
95        *self as _
96    }
97
98    fn try_to_usize(&self) -> Option<usize> {
99        Some(self.to_usize())
100    }
101}
102
103#[test]
104fn reparse() -> crate::Result<()> {
105    assert_eq!('x'.reparse()?, 'x');
106    assert_eq!('ч'.reparse()?, 'ч');
107    Ok(())
108}