1use crate::TinyAsciiStr;
6use alloc::borrow::Cow;
7use alloc::string::ToString;
8use core::fmt;
9use core::marker::PhantomData;
10use core::ops::Deref;
11use serde::de::{Error, SeqAccess, Visitor};
12use serde::ser::SerializeTuple;
13use serde::{Deserialize, Deserializer, Serialize, Serializer};
14
15impl<const N: usize> Serialize for TinyAsciiStr<N> {
16 #[inline]
17 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
18 where
19 S: Serializer,
20 {
21 if serializer.is_human_readable() {
22 self.deref().serialize(serializer)
23 } else {
24 let mut seq = serializer.serialize_tuple(N)?;
25 for byte in self.all_bytes() {
26 seq.serialize_element(byte)?;
27 }
28 seq.end()
29 }
30 }
31}
32
33struct TinyAsciiStrVisitor<const N: usize> {
34 marker: PhantomData<TinyAsciiStr<N>>,
35}
36
37impl<const N: usize> TinyAsciiStrVisitor<N> {
38 fn new() -> Self {
39 TinyAsciiStrVisitor {
40 marker: PhantomData,
41 }
42 }
43}
44
45impl<'de, const N: usize> Visitor<'de> for TinyAsciiStrVisitor<N> {
46 type Value = TinyAsciiStr<N>;
47
48 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
49 write!(formatter, "a TinyAsciiStr<{N}>")
50 }
51
52 #[inline]
53 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
54 where
55 A: SeqAccess<'de>,
56 {
57 let mut bytes = [0u8; N];
58 let mut zeroes = false;
59 for out in &mut bytes.iter_mut().take(N) {
60 let byte = seq
61 .next_element()?
62 .ok_or_else(|| Error::invalid_length(N, &self))?;
63 if byte == 0 {
64 zeroes = true;
65 } else if zeroes {
66 return Err(Error::custom("TinyAsciiStr cannot contain null bytes"));
67 }
68
69 if byte >= 0x80 {
70 return Err(Error::custom("TinyAsciiStr cannot contain non-ascii bytes"));
71 }
72 *out = byte;
73 }
74
75 Ok(unsafe { TinyAsciiStr::from_utf8_unchecked(bytes) })
76 }
77}
78
79impl<'de, const N: usize> Deserialize<'de> for TinyAsciiStr<N> {
80 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
81 where
82 D: Deserializer<'de>,
83 {
84 if deserializer.is_human_readable() {
85 let x: Cow<'de, str> = Deserialize::deserialize(deserializer)?;
86 TinyAsciiStr::try_from_str(&x).map_err(|e| Error::custom(e.to_string()))
87 } else {
88 deserializer.deserialize_tuple(N, TinyAsciiStrVisitor::<N>::new())
89 }
90 }
91}