aven_protocol/
base64_bytes.rs1use base64::{Engine, engine::general_purpose::STANDARD};
5use serde::{Deserializer, Serializer, de};
6
7pub const fn encoded_len(n: usize) -> usize {
9 match base64::encoded_len(n, true) {
10 Some(len) => len,
11 None => panic!("base64 length overflow"),
12 }
13}
14
15pub fn serialize<S: Serializer>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error> {
16 serializer.serialize_str(&STANDARD.encode(bytes))
17}
18
19pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<u8>, D::Error> {
20 deserializer.deserialize_str(Visitor(usize::MAX))
21}
22
23pub fn bounded<'de, D: Deserializer<'de>, const N: usize>(
25 deserializer: D,
26) -> Result<Vec<u8>, D::Error> {
27 deserializer.deserialize_str(Visitor(encoded_len(N)))
28}
29
30pub mod option {
32 use base64::Engine;
33 use serde::{Deserialize, Deserializer, Serializer};
34
35 #[derive(Deserialize)]
36 struct Bytes(#[serde(with = "super")] Vec<u8>);
37
38 pub fn serialize<S: Serializer>(
39 bytes: &Option<Vec<u8>>,
40 serializer: S,
41 ) -> Result<S::Ok, S::Error> {
42 match bytes {
43 Some(bytes) => serializer.serialize_some(&super::STANDARD.encode(bytes)),
44 None => serializer.serialize_none(),
45 }
46 }
47
48 pub fn deserialize<'de, D: Deserializer<'de>>(
49 deserializer: D,
50 ) -> Result<Option<Vec<u8>>, D::Error> {
51 Ok(Option::<Bytes>::deserialize(deserializer)?.map(|bytes| bytes.0))
52 }
53}
54
55struct Visitor(usize);
56impl de::Visitor<'_> for Visitor {
57 type Value = Vec<u8>;
58 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
59 write!(f, "a base64 string of at most {} characters", self.0)
60 }
61 fn visit_str<E: de::Error>(self, value: &str) -> Result<Vec<u8>, E> {
62 if value.len() > self.0 {
63 return Err(E::custom("byte limit"));
64 }
65 STANDARD.decode(value).map_err(E::custom)
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use serde::{Deserialize, Serialize};
72
73 #[derive(Serialize, Deserialize, PartialEq, Debug)]
74 struct Field(#[serde(with = "super")] Vec<u8>);
75
76 #[test]
77 fn round_trips_with_exact_length() {
78 for (n, encoded) in [
79 (0, 0),
80 (1, 4),
81 (2, 4),
82 (3, 4),
83 (4, 8),
84 (255, 340),
85 (1024, 1368),
86 ] {
87 let bytes: Vec<u8> = (0..n).map(|i| (i * 7) as u8).collect();
88 let json = serde_json::to_string(&Field(bytes.clone())).unwrap();
89 assert_eq!(super::encoded_len(n), encoded);
90 assert_eq!(json.len(), encoded + 2);
91 assert_eq!(serde_json::from_str::<Field>(&json).unwrap().0, bytes);
92 }
93 }
94
95 #[test]
96 fn rejects_other_spellings() {
97 for json in [
98 "[1,2,3]",
99 "\"AQID\\n\"",
100 "\"AQI\"",
101 "\"AQJ=\"",
102 "\"AQ-_\"",
103 "\"AQ==AQ==\"",
104 ] {
105 assert!(serde_json::from_str::<Field>(json).is_err(), "{json}");
106 }
107 #[derive(Deserialize)]
108 struct Bounded(#[serde(deserialize_with = "super::bounded::<_, 3>")] Vec<u8>);
109 assert_eq!(
110 serde_json::from_str::<Bounded>("\"AQID\"").unwrap().0,
111 [1, 2, 3]
112 );
113 assert!(serde_json::from_str::<Bounded>("\"AQIDBA==\"").is_err());
114 assert_eq!(
116 serde_json::from_str::<Field>("\"\\u0041QID\"").unwrap().0,
117 [1, 2, 3]
118 );
119 }
120}