static_id/
symbol.rs

1use serde::{Deserialize, Serialize};
2use std::ptr::copy_nonoverlapping;
3use std::str::from_utf8_unchecked;
4
5const END_MARK: u8 = 255;
6
7#[derive(Clone, Copy, PartialEq, Eq, Hash)]
8pub struct Symbol<const N: usize> {
9    symbol: [u8; N],
10}
11
12impl<const N: usize> std::fmt::Debug for Symbol<N> {
13    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14        write!(f, "{}", self.as_str())
15    }
16}
17
18impl<const N: usize> Default for Symbol<N> {
19    fn default() -> Self {
20        Self { symbol: [END_MARK; N] }
21    }
22}
23
24impl<const N: usize> Serialize for Symbol<N> {
25    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
26    where
27        S: serde::Serializer,
28    {
29        self.as_str().serialize(serializer)
30    }
31}
32
33impl<'de, const N: usize> Deserialize<'de> for Symbol<N> {
34    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
35    where
36        D: serde::Deserializer<'de>,
37    {
38        let s: String = String::deserialize(deserializer)?;
39        if s.len() > N {
40            return Err(serde::de::Error::custom(format!(
41                "String is too long. Expected at most {} characters, found {}",
42                N, s.len()
43            )));
44        }
45        Ok(Self::from(s.as_str()))
46    }
47}
48
49impl<const N: usize> From<&[u8]> for Symbol<N> {
50    #[inline]
51    fn from(slice: &[u8]) -> Self {
52        let mut symbol = [END_MARK; N];
53        let len = slice.len().min(N);
54        unsafe {
55            copy_nonoverlapping(slice.as_ptr(), symbol.as_mut_ptr(), len);
56        }
57        Self { symbol }
58    }
59}
60
61impl<const N: usize> From<&str> for Symbol<N> {
62    #[inline]
63    fn from(s: &str) -> Self {
64        Self::from(s.as_bytes())
65    }
66}
67
68impl<const N: usize> std::fmt::Display for Symbol<N> {
69    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70        write!(f, "{}", self.as_str())
71    }
72}
73
74impl<const N: usize> Symbol<N> {
75    #[inline]
76    pub fn len(&self) -> usize {
77        self.symbol.iter().position(|&c| c == END_MARK).unwrap_or(N)
78    }
79
80    #[inline]
81    pub fn upper_bound(&self) -> usize {
82        self.symbol.len()
83    }
84
85    #[inline]
86    pub fn is_empty(&self) -> bool {
87        self.symbol[0] == END_MARK
88    }
89    
90    #[inline]
91    #[must_use]
92    pub fn as_str(&self) -> &str {
93        let len = self.symbol.iter().position(|&c| c == END_MARK).unwrap_or(32);
94        unsafe { from_utf8_unchecked(&self.symbol[..len]) }
95    }
96
97    /// # Safety
98    /// The caller must ensure that the slice has at most `N` elements.
99    pub unsafe fn copy_from_slice(&mut self, slice: &[u8], length: usize) {
100        copy_nonoverlapping(slice.as_ptr(), self.symbol.as_mut_ptr(), length);
101    }
102}