]> git.proxmox.com Git - rustc.git/blob - vendor/zerovec/src/zerovec/serde.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / vendor / zerovec / src / zerovec / serde.rs
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::{ZeroSlice, ZeroVec};
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 core::mem;
12 use serde::de::{self, Deserialize, Deserializer, SeqAccess, Visitor};
13 #[cfg(feature = "serde")]
14 use serde::ser::{Serialize, SerializeSeq, Serializer};
15
16 struct ZeroVecVisitor<T> {
17 marker: PhantomData<fn() -> T>,
18 }
19
20 impl<T> Default for ZeroVecVisitor<T> {
21 fn default() -> Self {
22 Self {
23 marker: PhantomData,
24 }
25 }
26 }
27
28 impl<'de, T> Visitor<'de> for ZeroVecVisitor<T>
29 where
30 T: 'de + Deserialize<'de> + AsULE,
31 {
32 type Value = ZeroVec<'de, T>;
33
34 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
35 formatter.write_str("a sequence or borrowed buffer of fixed-width elements")
36 }
37
38 fn visit_borrowed_bytes<E>(self, bytes: &'de [u8]) -> Result<Self::Value, E>
39 where
40 E: de::Error,
41 {
42 ZeroVec::parse_byte_slice(bytes).map_err(de::Error::custom)
43 }
44
45 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
46 where
47 A: SeqAccess<'de>,
48 {
49 let mut vec: Vec<T::ULE> = if let Some(capacity) = seq.size_hint() {
50 Vec::with_capacity(capacity)
51 } else {
52 Vec::new()
53 };
54 while let Some(value) = seq.next_element::<T>()? {
55 vec.push(T::to_unaligned(value));
56 }
57 Ok(ZeroVec::new_owned(vec))
58 }
59 }
60
61 /// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
62 impl<'de, 'a, T> Deserialize<'de> for ZeroVec<'a, T>
63 where
64 T: 'de + Deserialize<'de> + AsULE,
65 'de: 'a,
66 {
67 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
68 where
69 D: Deserializer<'de>,
70 {
71 let visitor = ZeroVecVisitor::default();
72 if deserializer.is_human_readable() {
73 deserializer.deserialize_seq(visitor)
74 } else {
75 deserializer.deserialize_bytes(visitor)
76 }
77 }
78 }
79
80 /// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
81 impl<T> Serialize for ZeroVec<'_, T>
82 where
83 T: Serialize + AsULE,
84 {
85 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
86 where
87 S: Serializer,
88 {
89 if serializer.is_human_readable() {
90 let mut seq = serializer.serialize_seq(Some(self.len()))?;
91 for value in self.iter() {
92 seq.serialize_element(&value)?;
93 }
94 seq.end()
95 } else {
96 serializer.serialize_bytes(self.as_bytes())
97 }
98 }
99 }
100
101 /// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
102 impl<'de, T> Deserialize<'de> for Box<ZeroSlice<T>>
103 where
104 T: Deserialize<'de> + AsULE + 'static,
105 {
106 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
107 where
108 D: Deserializer<'de>,
109 {
110 let mut zv = ZeroVec::<T>::deserialize(deserializer)?;
111 let vec = zv.with_mut(mem::take);
112 Ok(ZeroSlice::from_boxed_slice(vec.into_boxed_slice()))
113 }
114 }
115
116 /// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
117 impl<'de, 'a, T> Deserialize<'de> for &'a ZeroSlice<T>
118 where
119 T: Deserialize<'de> + AsULE + 'static,
120 'de: 'a,
121 {
122 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
123 where
124 D: Deserializer<'de>,
125 {
126 if deserializer.is_human_readable() {
127 Err(de::Error::custom(
128 "&ZeroSlice cannot be deserialized from human-readable formats",
129 ))
130 } else {
131 let deserialized: ZeroVec<'a, T> = ZeroVec::deserialize(deserializer)?;
132 let borrowed = if let Some(b) = deserialized.as_maybe_borrowed() {
133 b
134 } else {
135 return Err(de::Error::custom(
136 "&ZeroSlice can only deserialize in zero-copy ways",
137 ));
138 };
139 Ok(borrowed)
140 }
141 }
142 }
143
144 /// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
145 impl<T> Serialize for ZeroSlice<T>
146 where
147 T: Serialize + AsULE,
148 {
149 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
150 where
151 S: Serializer,
152 {
153 self.as_zerovec().serialize(serializer)
154 }
155 }
156
157 #[cfg(test)]
158 #[allow(non_camel_case_types)]
159 mod test {
160 use crate::samples::*;
161 use crate::ZeroVec;
162
163 #[derive(serde::Serialize, serde::Deserialize)]
164 struct DeriveTest_ZeroVec<'data> {
165 #[serde(borrow)]
166 _data: ZeroVec<'data, u16>,
167 }
168
169 #[test]
170 fn test_serde_json() {
171 let zerovec_orig = ZeroVec::from_slice_or_alloc(TEST_SLICE);
172 let json_str = serde_json::to_string(&zerovec_orig).expect("serialize");
173 assert_eq!(JSON_STR, json_str);
174 // ZeroVec should deserialize from JSON to either Vec or ZeroVec
175 let vec_new: Vec<u32> =
176 serde_json::from_str(&json_str).expect("deserialize from buffer to Vec");
177 assert_eq!(
178 zerovec_orig,
179 ZeroVec::<u32>::from_slice_or_alloc(vec_new.as_slice())
180 );
181 let zerovec_new: ZeroVec<u32> =
182 serde_json::from_str(&json_str).expect("deserialize from buffer to ZeroVec");
183 assert_eq!(zerovec_orig, zerovec_new);
184 assert!(zerovec_new.is_owned());
185 }
186
187 #[test]
188 fn test_serde_bincode() {
189 let zerovec_orig = ZeroVec::from_slice_or_alloc(TEST_SLICE);
190 let bincode_buf = bincode::serialize(&zerovec_orig).expect("serialize");
191 assert_eq!(BINCODE_BUF, bincode_buf);
192 // ZeroVec should deserialize from Bincode to ZeroVec but not Vec
193 bincode::deserialize::<Vec<u32>>(&bincode_buf).expect_err("deserialize from buffer to Vec");
194 let zerovec_new: ZeroVec<u32> =
195 bincode::deserialize(&bincode_buf).expect("deserialize from buffer to ZeroVec");
196 assert_eq!(zerovec_orig, zerovec_new);
197
198 assert!(!zerovec_new.is_owned());
199 }
200
201 #[test]
202 fn test_chars_valid() {
203 // 1-byte, 2-byte, 3-byte, and 4-byte character in UTF-8 (not as relevant in UTF-32)
204 let zerovec_orig = ZeroVec::alloc_from_slice(&['w', 'ω', '文', '𑄃']);
205 let bincode_buf = bincode::serialize(&zerovec_orig).expect("serialize");
206 let zerovec_new: ZeroVec<char> =
207 bincode::deserialize(&bincode_buf).expect("deserialize from buffer to ZeroVec");
208 assert_eq!(zerovec_orig, zerovec_new);
209
210 assert!(!zerovec_new.is_owned());
211 }
212
213 #[test]
214 fn test_chars_invalid() {
215 // 119 and 120 are valid, but not 0xD800 (high surrogate)
216 let zerovec_orig: ZeroVec<u32> = ZeroVec::from_slice_or_alloc(&[119, 0xD800, 120]);
217 let bincode_buf = bincode::serialize(&zerovec_orig).expect("serialize");
218 let zerovec_result = bincode::deserialize::<ZeroVec<char>>(&bincode_buf);
219 assert!(matches!(zerovec_result, Err(_)));
220 }
221 }