biscuit/serde_custom/
byte_sequence.rs1use std::fmt;
3
4use data_encoding::BASE64URL_NOPAD;
5use serde::de;
6use serde::{Deserializer, Serializer};
7
8pub fn serialize<S>(value: &[u8], serializer: S) -> Result<S::Ok, S::Error>
10where
11 S: Serializer,
12{
13 let base64 = BASE64URL_NOPAD.encode(value);
14 serializer.serialize_str(&base64)
15}
16
17pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
19where
20 D: Deserializer<'de>,
21{
22 struct BytesVisitor;
23
24 impl<'de> de::Visitor<'de> for BytesVisitor {
25 type Value = Vec<u8>;
26
27 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
28 formatter.write_str("a URL safe base64 encoding of a byte sequence")
29 }
30
31 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
32 where
33 E: de::Error,
34 {
35 let bytes = BASE64URL_NOPAD
36 .decode(value.as_bytes())
37 .map_err(E::custom)?;
38 Ok(bytes)
39 }
40 }
41
42 deserializer.deserialize_str(BytesVisitor)
43}
44
45pub struct Wrapper<'a>(&'a [u8]);
46
47pub fn wrap(data: &[u8]) -> Wrapper {
48 Wrapper(data)
49}
50
51impl<'a> serde::Serialize for Wrapper<'a> {
52 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
53 where
54 S: Serializer,
55 {
56 serialize(self.0, serializer)
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use serde::{Deserialize, Serialize};
63 use serde_test::{assert_tokens, Token};
64
65 #[derive(Serialize, Deserialize, Eq, PartialEq, Debug)]
66 struct TestStruct {
67 #[serde(with = "super")]
68 bytes: Vec<u8>,
69 }
70
71 #[test]
72 fn serialization_round_trip() {
73 let test_value = TestStruct {
74 bytes: "hello world".to_string().into_bytes(),
75 };
76
77 assert_tokens(
78 &test_value,
79 &[
80 Token::Struct {
81 name: "TestStruct",
82 len: 1,
83 },
84 Token::Str("bytes"),
85 Token::Str("aGVsbG8gd29ybGQ"),
86 Token::StructEnd,
87 ],
88 );
89 }
90}