1use core::{
2 borrow::{Borrow, BorrowMut},
3 ffi::CStr,
4 fmt::Display,
5 ops::{Deref, DerefMut},
6 str::FromStr,
7};
8use core::{fmt, str};
9
10use alloc::{
11 borrow::ToOwned,
12 string::{String, ToString},
13 vec,
14};
15
16use crate::{
17 decode::{Decode, DecodeError, DecodeErrorKind, DecodeWithLength},
18 encode::Encode,
19};
20
21#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Hash)]
33pub struct FixedString<const N: usize>([u8; N]);
34
35impl<const N: usize> FixedString<N> {
36 pub fn new(s: impl AsRef<str>) -> Result<Self, FixedStringSizeError> {
45 let size = s.as_ref().as_bytes().len();
46
47 if size > N {
48 return Err(FixedStringSizeError {
49 input_size: size,
50 max_size: N,
51 });
52 }
53
54 Ok(unsafe { Self::new_unchecked(s) })
56 }
57
58 pub unsafe fn new_unchecked(s: impl AsRef<str>) -> Self {
71 let s = s.as_ref();
72 let bytes = s.as_bytes();
73 let len = bytes.len().min(N); let mut buf = [0; N];
76 buf[..len].copy_from_slice(&bytes[..len]);
77
78 Self(buf)
79 }
80
81 pub fn as_str(&self) -> &str {
83 let len = self.0.iter().position(|&b| b == 0).unwrap_or(N);
84
85 unsafe { str::from_utf8_unchecked(&self.0[..len]) }
87 }
88
89 pub fn as_mut_str(&mut self) -> &mut str {
91 let len = self.0.iter().position(|&b| b == 0).unwrap_or(N);
92
93 unsafe { str::from_utf8_unchecked_mut(&mut self.0[..len]) }
94 }
95}
96
97impl<const N: usize> Deref for FixedString<N> {
98 type Target = str;
99
100 fn deref(&self) -> &str {
101 self.as_str()
102 }
103}
104
105impl<const N: usize> DerefMut for FixedString<N> {
106 fn deref_mut(&mut self) -> &mut str {
107 self.as_mut_str()
108 }
109}
110
111impl<const N: usize> Default for FixedString<N> {
112 fn default() -> Self {
113 Self([0; N])
114 }
115}
116
117impl<const N: usize> AsRef<str> for FixedString<N> {
118 fn as_ref(&self) -> &str {
119 self
120 }
121}
122
123impl<const N: usize> AsMut<str> for FixedString<N> {
124 fn as_mut(&mut self) -> &mut str {
125 self
126 }
127}
128
129impl<const N: usize> Borrow<str> for FixedString<N> {
130 #[inline]
131 fn borrow(&self) -> &str {
132 &self[..]
133 }
134}
135
136impl<const N: usize> BorrowMut<str> for FixedString<N> {
137 #[inline]
138 fn borrow_mut(&mut self) -> &mut str {
139 &mut self[..]
140 }
141}
142
143impl<const N: usize> AsRef<[u8]> for FixedString<N> {
144 #[inline]
145 fn as_ref(&self) -> &[u8] {
146 self.as_bytes()
147 }
148}
149
150impl<const N: usize> TryFrom<&str> for FixedString<N> {
151 type Error = FixedStringSizeError;
152
153 fn try_from(value: &str) -> Result<FixedString<N>, FixedStringSizeError> {
154 Self::new(value)
155 }
156}
157
158impl<const N: usize> TryFrom<&mut str> for FixedString<N> {
159 type Error = FixedStringSizeError;
160
161 fn try_from(value: &mut str) -> Result<FixedString<N>, FixedStringSizeError> {
162 Self::new(value)
163 }
164}
165
166impl<const N: usize> FromStr for FixedString<N> {
167 type Err = FixedStringSizeError;
168
169 fn from_str(s: &str) -> Result<Self, Self::Err> {
170 Self::new(s.to_string())
171 }
172}
173
174impl<const N: usize> Display for FixedString<N> {
175 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176 self.as_str().fmt(f)
177 }
178}
179
180impl<const N: usize> Encode for FixedString<N> {
181 fn size(&self) -> usize {
182 N + 1
183 }
184
185 fn encode(&self, data: &mut [u8]) {
186 let data_len = self.0.len();
187
188 data[..data_len].copy_from_slice(self.as_bytes());
189 data[data_len + 1] = 0; }
191}
192
193impl<const N: usize> Decode for FixedString<N> {
194 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
195 Ok(unsafe { Self::new_unchecked(String::decode_with_len(data, N)?) })
196 }
197}
198
199#[derive(Clone, PartialEq, Eq, Debug)]
201pub struct FixedStringSizeError {
202 pub input_size: usize,
203 pub max_size: usize,
204}
205
206impl fmt::Display for FixedStringSizeError {
207 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
208 write!(
209 f,
210 "string with size {} exceeds the maximum size of FixedString<{}>",
211 self.input_size, self.max_size
212 )
213 }
214}
215
216impl core::error::Error for FixedStringSizeError {
217 fn description(&self) -> &str {
218 "string exceeds the maximum size of FixedString"
219 }
220}
221
222impl Encode for &str {
223 fn size(&self) -> usize {
224 self.len() + 1 }
226
227 fn encode(&self, data: &mut [u8]) {
228 let bytes = self.as_bytes();
229
230 data[..bytes.len()].copy_from_slice(bytes);
231 data[bytes.len()] = 0;
232 }
233}
234
235impl Encode for String {
236 fn size(&self) -> usize {
237 self.as_str().size()
238 }
239
240 fn encode(&self, data: &mut [u8]) {
241 self.as_str().encode(data)
242 }
243}
244
245impl DecodeWithLength for String {
246 fn decode_with_len(data: &mut &[u8], len: usize) -> Result<Self, DecodeError> {
247 let max_size = len as _;
248
249 let mut utf8 = vec![0u8; max_size];
250 for (i, string_byte) in utf8.iter_mut().enumerate() {
251 let byte = u8::decode(data)?;
252
253 if i == max_size {
254 if byte != 0 {
255 return Err(DecodeError::new::<Self>(
256 DecodeErrorKind::UnterminatedString,
257 ));
258 }
259 break;
260 }
261 if byte == 0 {
262 break;
263 }
264
265 *string_byte = byte;
266 }
267
268 let cstr = CStr::from_bytes_until_nul(&utf8)
269 .map_err(|_| DecodeError::new::<Self>(DecodeErrorKind::UnterminatedString))?;
270
271 Ok(cstr
272 .to_str()
273 .map_err(|e| DecodeError::new::<Self>(e.into()))?
274 .to_owned())
275 }
276}