ax_types/types/
binary.rs

1use base64::DecodeError;
2use derive_more::{From, Into};
3use fmt::Display;
4use serde::{
5    de::{self, Visitor},
6    Deserialize, Deserializer, Serialize, Serializer,
7};
8use std::{
9    fmt::{self, Formatter},
10    str::FromStr,
11};
12
13#[derive(Debug, Clone, From, Into, Ord, PartialOrd, Eq, PartialEq)]
14pub struct Binary(Box<[u8]>);
15
16struct X;
17impl<'de> Visitor<'de> for X {
18    type Value = Binary;
19    fn expecting(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
20        f.write_str("binary data (possibly base64-encoded)")
21    }
22    fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<Self::Value, E> {
23        Ok(Binary(v.into()))
24    }
25    fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
26        let bytes = base64::decode(v).map_err(|e| E::custom(e.to_string()))?;
27        Ok(Binary(bytes.into()))
28    }
29}
30
31impl<'de> Deserialize<'de> for Binary {
32    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
33        deserializer.deserialize_any(X)
34    }
35}
36
37impl Serialize for Binary {
38    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
39        if serializer.is_human_readable() {
40            serializer.serialize_str(base64::encode(&*self.0).as_str())
41        } else {
42            serializer.serialize_bytes(&self.0)
43        }
44    }
45}
46
47impl FromStr for Binary {
48    type Err = DecodeError;
49    fn from_str(s: &str) -> Result<Self, Self::Err> {
50        let bytes = base64::decode(s)?;
51        Ok(Binary(bytes.into()))
52    }
53}
54
55impl AsRef<[u8]> for Binary {
56    fn as_ref(&self) -> &[u8] {
57        &self.0
58    }
59}
60
61impl Display for Binary {
62    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
63        f.write_str(base64::encode(&*self.0).as_str())
64    }
65}
66
67impl From<&[u8]> for Binary {
68    fn from(v: &[u8]) -> Self {
69        Binary(v.into())
70    }
71}
72
73impl From<Vec<u8>> for Binary {
74    fn from(v: Vec<u8>) -> Self {
75        Binary(v.into())
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    #[test]
84    fn must_serialize_json() {
85        let binary = Binary((&[1, 2, 3, 255][..]).into());
86        let text = serde_json::to_string(&binary).unwrap();
87        assert_eq!(text, r#""AQID/w==""#);
88        assert_eq!(serde_json::from_str::<Binary>(&text).unwrap(), binary);
89    }
90
91    #[test]
92    fn must_serialize_cbor() {
93        let binary = Binary((&[1, 2, 3][..]).into());
94        let cbor = serde_cbor::to_vec(&binary).unwrap();
95        assert_eq!(cbor, vec![67, 1, 2, 3]);
96        assert_eq!(serde_cbor::from_slice::<Binary>(&cbor).unwrap(), binary);
97    }
98}