cgp_field/traits/
static_string.rs

1use crate::types::{Chars, Nil, Symbol};
2
3pub trait StaticString {
4    const VALUE: &'static str;
5}
6
7impl<T> StaticString for T
8where
9    T: StaticBytes,
10{
11    const VALUE: &'static str = const {
12        match str::from_utf8(T::BYTES) {
13            Ok(value) => value,
14            Err(_) => panic!("error const decoding &[u8] to &str"),
15        }
16    };
17}
18
19trait StaticBytes {
20    const BYTES: &'static [u8];
21}
22
23trait MaybeChars {
24    const VALUE: Option<char>;
25
26    type Next: MaybeChars;
27}
28
29impl<const LEN: usize, Chars> StaticBytes for Symbol<LEN, Chars>
30where
31    Chars: MaybeChars,
32{
33    const BYTES: &'static [u8] = &static_chars::<LEN, Chars>();
34}
35
36impl StaticBytes for Nil {
37    const BYTES: &'static [u8] = &[];
38}
39
40impl<const CHAR: char, Tail> MaybeChars for Chars<CHAR, Tail>
41where
42    Tail: MaybeChars,
43{
44    const VALUE: Option<char> = Some(CHAR);
45
46    type Next = Tail;
47}
48
49impl MaybeChars for Nil {
50    const VALUE: Option<char> = None;
51
52    type Next = Nil;
53}
54
55const fn static_chars<const LEN: usize, S: MaybeChars>() -> [u8; LEN] {
56    let mut chars = [0; LEN];
57
58    update_chars::<S>(&mut chars);
59
60    chars
61}
62
63const fn update_chars<S: MaybeChars>(mut chars: &mut [u8]) {
64    if let Some(value) = S::VALUE {
65        value.encode_utf8(chars);
66
67        let len = value.len_utf8();
68
69        let mut j = 0;
70        while j < len {
71            chars = chars.split_first_mut().unwrap().1;
72            j += 1;
73        }
74
75        update_chars::<S::Next>(chars);
76    }
77}