1 // This file is part of ICU4X. For terms of use, please see the file 2 // called LICENSE at the top level of the ICU4X source tree 3 // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). 4 5 use super::{VarZeroSlice, VarZeroVec, VarZeroVecFormat}; 6 use crate::ule::*; 7 use alloc::boxed::Box; 8 use alloc::vec::Vec; 9 use core::fmt; 10 use core::marker::PhantomData; 11 use serde::de::{self, Deserialize, Deserializer, SeqAccess, Visitor}; 12 #[cfg(feature = "serde")] 13 use serde::ser::{Serialize, SerializeSeq, Serializer}; 14 15 struct VarZeroVecVisitor<T: ?Sized, F: VarZeroVecFormat> { 16 #[allow(clippy::type_complexity)] // this is a private marker type, who cares 17 marker: PhantomData<(fn() -> Box<T>, F)>, 18 } 19 20 impl<T: ?Sized, F: VarZeroVecFormat> Default for VarZeroVecVisitor<T, F> { default() -> Self21 fn default() -> Self { 22 Self { 23 marker: PhantomData, 24 } 25 } 26 } 27 28 impl<'de, T, F> Visitor<'de> for VarZeroVecVisitor<T, F> 29 where 30 T: VarULE + ?Sized, 31 Box<T>: Deserialize<'de>, 32 F: VarZeroVecFormat, 33 { 34 type Value = VarZeroVec<'de, T, F>; 35 expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result36 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 37 formatter.write_str("a sequence or borrowed buffer of bytes") 38 } 39 visit_borrowed_bytes<E>(self, bytes: &'de [u8]) -> Result<Self::Value, E> where E: de::Error,40 fn visit_borrowed_bytes<E>(self, bytes: &'de [u8]) -> Result<Self::Value, E> 41 where 42 E: de::Error, 43 { 44 VarZeroVec::parse_bytes(bytes).map_err(de::Error::custom) 45 } 46 visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> where A: SeqAccess<'de>,47 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> 48 where 49 A: SeqAccess<'de>, 50 { 51 let mut vec: Vec<Box<T>> = if let Some(capacity) = seq.size_hint() { 52 Vec::with_capacity(capacity) 53 } else { 54 Vec::new() 55 }; 56 while let Some(value) = seq.next_element::<Box<T>>()? { 57 vec.push(value); 58 } 59 Ok(VarZeroVec::from(&vec)) 60 } 61 } 62 63 /// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate 64 impl<'de, 'a, T, F> Deserialize<'de> for VarZeroVec<'a, T, F> 65 where 66 T: VarULE + ?Sized, 67 Box<T>: Deserialize<'de>, 68 F: VarZeroVecFormat, 69 'de: 'a, 70 { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,71 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 72 where 73 D: Deserializer<'de>, 74 { 75 let visitor = VarZeroVecVisitor::<T, F>::default(); 76 if deserializer.is_human_readable() { 77 deserializer.deserialize_seq(visitor) 78 } else { 79 deserializer.deserialize_bytes(visitor) 80 } 81 } 82 } 83 84 /// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate 85 impl<'de, 'a, T, F> Deserialize<'de> for &'a VarZeroSlice<T, F> 86 where 87 T: VarULE + ?Sized, 88 F: VarZeroVecFormat, 89 'de: 'a, 90 { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,91 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 92 where 93 D: Deserializer<'de>, 94 { 95 if deserializer.is_human_readable() { 96 Err(de::Error::custom( 97 "&VarZeroSlice cannot be deserialized from human-readable formats", 98 )) 99 } else { 100 let bytes = <&[u8]>::deserialize(deserializer)?; 101 VarZeroSlice::<T, F>::parse_bytes(bytes).map_err(de::Error::custom) 102 } 103 } 104 } 105 106 /// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate 107 impl<'de, T, F> Deserialize<'de> for Box<VarZeroSlice<T, F>> 108 where 109 T: VarULE + ?Sized, 110 Box<T>: Deserialize<'de>, 111 F: VarZeroVecFormat, 112 { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,113 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 114 where 115 D: Deserializer<'de>, 116 { 117 let deserialized = VarZeroVec::<T, F>::deserialize(deserializer)?; 118 Ok(deserialized.to_boxed()) 119 } 120 } 121 122 /// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate 123 #[cfg(feature = "serde")] 124 impl<T, F> Serialize for VarZeroVec<'_, T, F> 125 where 126 T: Serialize + VarULE + ?Sized, 127 F: VarZeroVecFormat, 128 { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,129 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 130 where 131 S: Serializer, 132 { 133 if serializer.is_human_readable() { 134 let mut seq = serializer.serialize_seq(Some(self.len()))?; 135 for value in self.iter() { 136 seq.serialize_element(value)?; 137 } 138 seq.end() 139 } else { 140 serializer.serialize_bytes(self.as_bytes()) 141 } 142 } 143 } 144 145 /// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate 146 #[cfg(feature = "serde")] 147 impl<T, F> Serialize for VarZeroSlice<T, F> 148 where 149 T: Serialize + VarULE + ?Sized, 150 F: VarZeroVecFormat, 151 { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,152 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 153 where 154 S: Serializer, 155 { 156 self.as_varzerovec().serialize(serializer) 157 } 158 } 159 160 #[cfg(test)] 161 #[allow(non_camel_case_types)] 162 mod test { 163 use crate::{VarZeroSlice, VarZeroVec}; 164 165 #[derive(serde::Serialize, serde::Deserialize)] 166 struct DeriveTest_VarZeroVec<'data> { 167 #[serde(borrow)] 168 _data: VarZeroVec<'data, str>, 169 } 170 171 #[derive(serde::Serialize, serde::Deserialize)] 172 struct DeriveTest_VarZeroSlice<'data> { 173 #[serde(borrow)] 174 _data: &'data VarZeroSlice<str>, 175 } 176 177 #[derive(serde::Serialize, serde::Deserialize)] 178 struct DeriveTest_VarZeroVec_of_VarZeroSlice<'data> { 179 #[serde(borrow)] 180 _data: VarZeroVec<'data, VarZeroSlice<str>>, 181 } 182 183 // ["foo", "bar", "baz", "dolor", "quux", "lorem ipsum"]; 184 const BYTES: &[u8] = &[ 185 6, 0, 3, 0, 6, 0, 9, 0, 14, 0, 18, 0, 102, 111, 111, 98, 97, 114, 98, 97, 122, 100, 111, 186 108, 111, 114, 113, 117, 117, 120, 108, 111, 114, 101, 109, 32, 105, 112, 115, 117, 109, 187 ]; 188 const JSON_STR: &str = "[\"foo\",\"bar\",\"baz\",\"dolor\",\"quux\",\"lorem ipsum\"]"; 189 const BINCODE_BUF: &[u8] = &[ 190 41, 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, 0, 6, 0, 9, 0, 14, 0, 18, 0, 102, 111, 111, 98, 97, 114, 191 98, 97, 122, 100, 111, 108, 111, 114, 113, 117, 117, 120, 108, 111, 114, 101, 109, 32, 105, 192 112, 115, 117, 109, 193 ]; 194 195 // ["w", "ω", "文", ""] 196 const NONASCII_STR: &[&str] = &["w", "ω", "文", ""]; 197 const NONASCII_BYTES: &[u8] = &[ 198 4, 0, 1, 0, 3, 0, 6, 0, 119, 207, 137, 230, 150, 135, 240, 145, 132, 131, 199 ]; 200 #[test] test_serde_json()201 fn test_serde_json() { 202 let zerovec_orig: VarZeroVec<str> = VarZeroVec::parse_bytes(BYTES).expect("parse"); 203 let json_str = serde_json::to_string(&zerovec_orig).expect("serialize"); 204 assert_eq!(JSON_STR, json_str); 205 // VarZeroVec should deserialize from JSON to either Vec or VarZeroVec 206 let vec_new: Vec<Box<str>> = 207 serde_json::from_str(&json_str).expect("deserialize from buffer to Vec"); 208 assert_eq!(zerovec_orig.to_vec(), vec_new); 209 let zerovec_new: VarZeroVec<str> = 210 serde_json::from_str(&json_str).expect("deserialize from buffer to VarZeroVec"); 211 assert_eq!(zerovec_orig.to_vec(), zerovec_new.to_vec()); 212 assert!(zerovec_new.is_owned()); 213 } 214 215 #[test] test_serde_bincode()216 fn test_serde_bincode() { 217 let zerovec_orig: VarZeroVec<str> = VarZeroVec::parse_bytes(BYTES).expect("parse"); 218 let bincode_buf = bincode::serialize(&zerovec_orig).expect("serialize"); 219 assert_eq!(BINCODE_BUF, bincode_buf); 220 let zerovec_new: VarZeroVec<str> = 221 bincode::deserialize(&bincode_buf).expect("deserialize from buffer to VarZeroVec"); 222 assert_eq!(zerovec_orig.to_vec(), zerovec_new.to_vec()); 223 assert!(!zerovec_new.is_owned()); 224 } 225 226 #[test] test_vzv_borrowed()227 fn test_vzv_borrowed() { 228 let zerovec_orig: &VarZeroSlice<str> = VarZeroSlice::parse_bytes(BYTES).expect("parse"); 229 let bincode_buf = bincode::serialize(&zerovec_orig).expect("serialize"); 230 assert_eq!(BINCODE_BUF, bincode_buf); 231 let zerovec_new: &VarZeroSlice<str> = 232 bincode::deserialize(&bincode_buf).expect("deserialize from buffer to VarZeroSlice"); 233 assert_eq!(zerovec_orig.to_vec(), zerovec_new.to_vec()); 234 } 235 236 #[test] test_nonascii_bincode()237 fn test_nonascii_bincode() { 238 let src_vec = NONASCII_STR 239 .iter() 240 .copied() 241 .map(Box::<str>::from) 242 .collect::<Vec<_>>(); 243 let mut zerovec: VarZeroVec<str> = VarZeroVec::parse_bytes(NONASCII_BYTES).expect("parse"); 244 assert_eq!(zerovec.to_vec(), src_vec); 245 let bincode_buf = bincode::serialize(&zerovec).expect("serialize"); 246 let zerovec_result = 247 bincode::deserialize::<VarZeroVec<str>>(&bincode_buf).expect("deserialize"); 248 assert_eq!(zerovec_result.to_vec(), src_vec); 249 250 // try again with owned zerovec 251 zerovec.make_mut(); 252 let bincode_buf = bincode::serialize(&zerovec).expect("serialize"); 253 let zerovec_result = 254 bincode::deserialize::<VarZeroVec<str>>(&bincode_buf).expect("deserialize"); 255 assert_eq!(zerovec_result.to_vec(), src_vec); 256 } 257 } 258