A better Rust ATProto crate
103
fork

Configure Feed

Select the types of activity you want to include in your feed.

at pretty-codegen 90 lines 2.9 kB view raw
1//! Custom serde helpers for bytes::Bytes using serde_bytes 2 3use alloc::string::String; 4use alloc::vec::Vec; 5use core::fmt; 6 7use base64::{ 8 Engine, 9 prelude::{BASE64_STANDARD, BASE64_STANDARD_NO_PAD, BASE64_URL_SAFE, BASE64_URL_SAFE_NO_PAD}, 10}; 11use bytes::Bytes; 12use serde::{ 13 Deserializer, Serializer, 14 de::{self, MapAccess, Visitor}, 15}; 16 17/// Serialize Bytes as a CBOR byte string 18pub fn serialize<S>(bytes: &Bytes, serializer: S) -> Result<S::Ok, S::Error> 19where 20 S: Serializer, 21{ 22 if serializer.is_human_readable() { 23 // JSON: {"$bytes": "base64 string"} 24 use serde::ser::SerializeMap; 25 let mut map = serializer.serialize_map(Some(1))?; 26 map.serialize_entry("$bytes", &BASE64_STANDARD.encode(bytes))?; 27 map.end() 28 } else { 29 // CBOR: raw bytes 30 serde_bytes::serialize(bytes.as_ref(), serializer) 31 } 32} 33 34/// Deserialize Bytes from a CBOR byte string 35pub fn deserialize<'de, D>(deserializer: D) -> Result<Bytes, D::Error> 36where 37 D: Deserializer<'de>, 38{ 39 if deserializer.is_human_readable() { 40 Ok(deserializer.deserialize_map(BytesVisitor)?) 41 } else { 42 let vec: Vec<u8> = serde_bytes::deserialize(deserializer)?; 43 Ok(Bytes::from(vec)) 44 } 45} 46 47struct BytesVisitor; 48 49impl<'de> Visitor<'de> for BytesVisitor { 50 type Value = Bytes; 51 52 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 53 formatter.write_str("a base64-encoded string") 54 } 55 56 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error> 57 where 58 A: MapAccess<'de>, 59 { 60 let mut bytes = None; 61 62 while let Some(key) = map.next_key()? { 63 match key { 64 "$bytes" => { 65 if bytes.is_some() { 66 return Err(de::Error::duplicate_field("$bytes")); 67 } 68 let bytes_str: String = map.next_value()?; 69 // First one should just work. rest are insurance. 70 bytes = if let Ok(bytes) = BASE64_STANDARD.decode(&bytes_str) { 71 Some(Bytes::from_owner(bytes)) 72 } else if let Ok(bytes) = BASE64_STANDARD_NO_PAD.decode(&bytes_str) { 73 Some(Bytes::from_owner(bytes)) 74 } else if let Ok(bytes) = BASE64_URL_SAFE.decode(&bytes_str) { 75 Some(Bytes::from_owner(bytes)) 76 } else if let Ok(bytes) = BASE64_URL_SAFE_NO_PAD.decode(&bytes_str) { 77 Some(Bytes::from_owner(bytes)) 78 } else { 79 return Err(de::Error::custom("invalid base64 string")); 80 } 81 } 82 _ => { 83 return Err(de::Error::unknown_field(key, &["$bytes"])); 84 } 85 } 86 } 87 88 bytes.ok_or_else(|| de::Error::missing_field("$bytes")) 89 } 90}