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 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}