null_terminated_str/
serde_impl.rs

1use std::ops::Deref;
2
3use serde::{
4    de::{Deserialize, Deserializer, Error, Unexpected},
5    Serialize, Serializer,
6};
7
8use super::{NullTerminatedStr, NullTerminatedString};
9
10impl Serialize for NullTerminatedStr {
11    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
12    where
13        S: Serializer,
14    {
15        serializer.serialize_bytes(self.as_c_str().to_bytes_with_nul())
16    }
17}
18
19impl Serialize for NullTerminatedString {
20    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
21    where
22        S: Serializer,
23    {
24        self.deref().serialize(serializer)
25    }
26}
27
28impl<'de: 'a, 'a> Deserialize<'de> for &'a NullTerminatedStr {
29    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
30    where
31        D: Deserializer<'de>,
32    {
33        let s = <&str>::deserialize(deserializer)?;
34        NullTerminatedStr::try_from_str(s).ok_or_else(|| {
35            D::Error::invalid_value(Unexpected::Str(s), &"Expected null terminated utf-8 str")
36        })
37    }
38}
39
40impl<'de> Deserialize<'de> for NullTerminatedString {
41    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
42    where
43        D: Deserializer<'de>,
44    {
45        let s = <String>::deserialize(deserializer)?;
46        Ok(NullTerminatedString::from(s))
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use crate::{const_null_terminated_str, NullTerminatedStr, NullTerminatedString};
53    use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token};
54
55    #[test]
56    fn test_de_ser_null_terminated_str() {
57        macro_rules! def_str_test {
58            ($s:expr) => {
59                assert_tokens(
60                    &const_null_terminated_str!($s),
61                    &[Token::BorrowedBytes(concat!($s, "\0").as_bytes())],
62                );
63
64                assert_tokens(
65                    &(const_null_terminated_str!($s)).to_owned(),
66                    &[Token::BorrowedBytes(concat!($s, "\0").as_bytes())],
67                );
68            };
69        }
70
71        def_str_test!("");
72        def_str_test!("abcde");
73    }
74
75    #[test]
76    fn test_de_ser_null_terminated_str_err() {
77        let strs: &[&str] = &["", "abcde"];
78
79        for s in strs {
80            let byte = s.as_bytes();
81            assert_de_tokens_error::<&NullTerminatedStr>(
82                &[Token::BorrowedBytes(byte)],
83                &format!(
84                    r#"invalid value: string "{}", expected Expected null terminated utf-8 str"#,
85                    s
86                ),
87            );
88
89            assert_de_tokens::<NullTerminatedString>(
90                &NullTerminatedString::from(*s),
91                &[Token::BorrowedBytes(byte)],
92            );
93        }
94    }
95}