Skip to main content

reliq/utf8/
mod.rs

1use super::*;
2
3pub type Result<T> = ::core::result::Result<T, Error>;
4
5#[repr(u8)]
6#[derive(Debug)]
7#[derive(Clone)]
8#[derive(PartialEq)]
9#[derive(Eq)]
10#[derive(PartialOrd)]
11#[derive(Ord)]
12#[derive(Hash)]
13#[derive(::strum_macros::EnumCount)]
14#[derive(::strum_macros::EnumIs)]
15#[derive(::thiserror::Error)]
16#[derive(::serde::Serialize)]
17#[derive(::serde::Deserialize)]
18pub enum Error {
19    #[error("Overflow.")]
20    Overflow,
21    #[error("Invalid sequence.")]
22    InvalidSequence,
23    #[error("Empty.")]
24    Empty
25}
26
27#[derive(Clone)]
28#[derive(Hash)]
29#[derive(::serde::Serialize)]
30#[derive(::serde::Deserialize)]
31pub struct Utf8<const A: usize> {
32    buf: array::Array<A, u8>,
33    len: usize
34}
35
36impl<const A: usize> Utf8<A> {
37    #[inline]
38    pub const fn new() -> Self {
39        Self {
40            buf: array::Array {
41                buf: unsafe {
42                    core::mem::MaybeUninit::uninit().assume_init()
43                },
44                len: 0
45            },
46            len: 0
47        }
48    }
49
50    #[inline]
51    pub const fn encode<B>(bytes: &[u8]) -> Self {
52        let mut ret: Self = Self::new();
53        let mut key: usize = 0;
54        while key < bytes.len() && ret.buf.len < A {
55            let byte = bytes[key];
56            ret.buf.buf[key].write(byte);
57            ret.buf.len += 1;
58            if byte & 0b1100_0000 != 0b1000_0000 {
59                ret.len += 1
60            }
61            key += 1;
62        }
63        ret
64    }
65
66    #[inline] 
67    pub fn push_str(&mut self, s: &str) -> Result<()> {
68        let old_buf_len: usize = self.buf.len();
69        let old_len: usize = self.len;
70        for c in s.chars() {
71            if let Err(e) = self.push(c) {
72                self.buf.len = old_buf_len;
73                self.len = old_len;
74                return Err(e)
75            }
76        }
77        Ok(())
78    }
79
80    #[inline]
81    pub const fn push(&mut self, c: char) -> Result<()> {
82        let code: u32 = c as u32;
83        let arr: &mut array::Array<A, u8> = &mut self.buf;
84        let req: usize = if code <= 0x7f {
85            1
86        } else if code <= 0x7ff {
87            2
88        } else if code <= 0xffff {
89            3
90        } else {
91            4
92        };
93        if arr.len() + req > A {
94            return Err(Error::Overflow)
95        }
96        match req {
97            1 => {
98                let _ = arr.push(code as u8);
99            },
100            2 => {
101                let _ = arr.push((0b1100_0000 | ((code >> 6) & 0x1F)) as u8);
102                let _ = arr.push((0b1000_0000 | (code & 0x3F)) as u8);
103            },
104            3 => {
105                let _ = arr.push((0b1110_0000 | ((code >> 12) & 0x0F)) as u8);
106                let _ = arr.push((0b1000_0000 | ((code >> 6) & 0x3F)) as u8);
107                let _ = arr.push((0b1000_0000 | (code & 0x3F)) as u8);
108            },
109            4 => {
110                let _ = arr.push((0b1111_0000 | ((code >> 18) & 0x07)) as u8);
111                let _ = arr.push((0b1000_0000 | ((code >> 12) & 0x3F)) as u8);
112                let _ = arr.push((0b1000_0000 | ((code >> 6) & 0x3F)) as u8);
113                let _ = arr.push((0b1000_0000 | (code & 0x3F)) as u8);
114            },
115            _ => unreachable!()
116        }
117        self.len += 1;
118        Ok(())
119    }
120
121    #[inline]
122    pub const fn pop(&mut self) -> Result<()> {
123        let buf: &[u8] = self.buf.as_slice();
124        let key: usize = self.buf.len();
125        if key == 0 {
126            return Err(Error::Empty)
127        }
128        let mut back: usize = 1;
129        while back <= 4 {
130            if key < back {
131                break
132            }
133            let b: u8 = buf[key - back];
134            if back == 1 && b & 0b1000_0000 == 0 {
135                self.buf.len -= 1;
136                self.len -= 1;
137                return Ok(())
138            } else if back == 2 && b & 0b1110_0000 == 0b1100_0000 {
139                self.buf.len -= 2;
140                self.len -= 1;
141                return Ok(())
142            } else if back == 3 && b & 0b1111_0000 == 0b1110_0000 {
143                self.buf.len -= 3;
144                self.len -= 1;
145                return Ok(())
146            } else if back == 4 && b & 0b1111_1000 == 0b1111_0000 {
147                self.buf.len -= 4;
148                self.len -= 1;
149                return Ok(())
150            }
151            back += 1;
152        }
153        Err(Error::InvalidSequence)
154    }
155
156    pub fn cast<const B: usize>(self) -> Result<Utf8<B>> {
157        let a: Utf8<A> = self;
158        let a: &str = a.as_str();
159        let mut b: Utf8<B> = Utf8::new();
160        b.push_str(a)?;
161        Ok(b)
162    }
163
164    pub fn as_str(&self) -> &str {
165        let ret = self.buf.as_slice();
166        ::core::str::from_utf8(ret)
167            .ok()
168            .ok_or(Error::InvalidSequence)
169            .unwrap()
170    }
171}
172
173impl<const T: usize> Default for Utf8<T> {
174    fn default() -> Self {
175        Self::new()
176    }
177}
178
179impl<const T: usize> TryFrom<&str> for Utf8<T> {
180    type Error = Error;
181
182    fn try_from(value: &str) -> ::core::result::Result<Self, Self::Error> {
183        let mut s: Self = Self::new();
184        s.push_str(value)?;
185        Ok(s)
186    }
187}
188
189#[cfg(feature = "std")]
190impl<const T: usize> TryFrom<String> for Utf8<T> {
191    type Error = Error;
192
193    fn try_from(value: String) -> ::core::result::Result<Self, Self::Error> {
194        let value: &str = &value;
195        let mut s: Self = Self::new();
196        s.push_str(value)?;
197        Ok(s)
198    }
199}
200
201impl<const T: usize> Eq for Utf8<T> {}
202impl<const T: usize> PartialEq for Utf8<T> {
203    fn eq(&self, other: &Self) -> bool {
204        self.len == other.len && self.buf == other.buf
205    }
206}
207
208impl<const T: usize> Ord for Utf8<T> {
209    fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
210        let x: &str = self.as_str();
211        let y: &str = other.as_str();
212        x.cmp(y)
213    }
214}
215
216#[allow(clippy::non_canonical_partial_ord_impl)]
217impl<const T: usize> PartialOrd for Utf8<T> {
218    fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
219        let x: &str = self.as_str();
220        let y: &str = other.as_str();
221        let ret: ::core::cmp::Ordering = x.cmp(y);
222        Some(ret)
223    }
224}
225
226impl<const T: usize> ::core::fmt::Debug for Utf8<T> {
227    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
228        f
229            .debug_struct("Utf8")
230            .field("len", &self.len)
231            .field("buf_len", &self.buf.len)
232            .field("as_str", &self.as_str())
233            .finish()
234    }
235}
236
237impl<const T: usize> ::core::fmt::Display for Utf8<T> {
238    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
239        let s: &str = self.as_str();
240        write!(f, "{}", s)
241    }
242}
243
244#[test]
245fn test() {
246    let s: Utf8<32> = "Hello World".try_into().unwrap();
247    let s_ok: Utf8<32> = "Hello World".try_into().unwrap();
248    assert_eq!(s, s_ok);
249}
250