mina_p2p_messages/
char.rs

1use binprot::byteorder::{ReadBytesExt, WriteBytesExt};
2use serde::{de::Visitor, Deserialize, Serialize};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
5pub struct Char(pub u8);
6
7impl std::ops::Deref for Char {
8    type Target = u8;
9
10    fn deref(&self) -> &Self::Target {
11        &self.0
12    }
13}
14
15impl Char {
16    pub fn as_u8(&self) -> u8 {
17        self.0
18    }
19}
20
21impl Serialize for Char {
22    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
23    where
24        S: serde::Serializer,
25    {
26        if serializer.is_human_readable() {
27            char::from_u32(self.0.into())
28                .unwrap()
29                .to_string()
30                .serialize(serializer)
31        } else {
32            self.0.serialize(serializer)
33        }
34    }
35}
36
37impl<'de> Deserialize<'de> for Char {
38    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
39    where
40        D: serde::Deserializer<'de>,
41    {
42        fn str_to_char(v: &str) -> Result<u8, &str> {
43            if v.len() != 1 {
44                return Err("incorrect length");
45            }
46            let ch = v.chars().next().unwrap();
47            (ch as u32).try_into().map_err(|_| "incorrect char")
48        }
49        if deserializer.is_human_readable() {
50            struct V;
51            impl Visitor<'_> for V {
52                type Value = u8;
53
54                fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
55                    formatter.write_str("string consisting of a single escaped unicode character")
56                }
57
58                fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
59                where
60                    E: serde::de::Error,
61                {
62                    str_to_char(&v).map_err(serde::de::Error::custom)
63                }
64
65                fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
66                where
67                    E: serde::de::Error,
68                {
69                    str_to_char(v).map_err(serde::de::Error::custom)
70                }
71            }
72
73            deserializer.deserialize_string(V)
74        } else {
75            u8::deserialize(deserializer)
76        }
77        .map(Self)
78    }
79}
80
81impl From<u8> for Char {
82    fn from(source: u8) -> Self {
83        Self(source)
84    }
85}
86
87impl From<Char> for u8 {
88    fn from(source: Char) -> Self {
89        source.0
90    }
91}
92
93impl binprot::BinProtRead for Char {
94    fn binprot_read<R: std::io::Read + ?Sized>(r: &mut R) -> Result<Self, binprot::Error>
95    where
96        Self: Sized,
97    {
98        Ok(r.read_u8().map(Self)?)
99    }
100}
101
102impl binprot::BinProtWrite for Char {
103    fn binprot_write<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
104        w.write_u8(self.0)
105    }
106}
107
108#[cfg(test)]
109mod tests {
110
111    #[test]
112    fn json() {
113        let ch = super::Char(16);
114        let json = serde_json::to_value(ch).unwrap();
115        assert_eq!(json.as_str().unwrap(), "\u{0010}");
116        assert_eq!(
117            serde_json::from_value::<super::Char>(json).unwrap(),
118            super::Char(16)
119        );
120    }
121}