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 std::borrow::Cow;
6 use std::fmt::Debug;
7
8 use zerofrom::ZeroFrom;
9 use zerovec::{ule::AsULE, *};
10
11 #[make_varule(VarStructULE)]
12 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, serde::Serialize, serde::Deserialize)]
13 #[zerovec::derive(Serialize, Deserialize, Debug)]
14 struct VarStruct<'a> {
15 a: u32,
16 b: char,
17 #[serde(borrow)]
18 c: Cow<'a, str>,
19 }
20
21 #[make_varule(VarStructOutOfOrderULE)]
22 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, serde::Serialize, serde::Deserialize)]
23 #[zerovec::derive(Serialize, Deserialize, Debug)]
24 struct VarStructOutOfOrder<'a> {
25 a: u32,
26 #[serde(borrow)]
27 b: Cow<'a, str>,
28 c: char,
29 d: u8,
30 }
31
32 #[make_varule(VarTupleStructULE)]
33 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, serde::Serialize, serde::Deserialize)]
34 #[zerovec::derive(Serialize, Deserialize, Debug)]
35 struct VarTupleStruct<'a>(u32, char, #[serde(borrow)] VarZeroVec<'a, str>);
36
37 #[make_varule(NoKVULE)]
38 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, serde::Serialize, serde::Deserialize)]
39 #[zerovec::skip_derive(ZeroMapKV)]
40 #[zerovec::derive(Serialize, Deserialize, Debug)]
41 struct NoKV<'a>(u32, char, #[serde(borrow)] VarZeroVec<'a, str>);
42
43 #[make_varule(NoOrdULE)]
44 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, serde::Serialize, serde::Deserialize)]
45 #[zerovec::skip_derive(ZeroMapKV, Ord)]
46 #[zerovec::derive(Serialize, Deserialize, Debug)]
47 struct NoOrd<'a>(u32, char, #[serde(borrow)] VarZeroVec<'a, str>);
48
49 #[make_varule(MultiFieldStructULE)]
50 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, serde::Serialize, serde::Deserialize)]
51 #[zerovec::derive(Serialize, Deserialize, Debug)]
52 struct MultiFieldStruct<'a> {
53 a: u32,
54 b: char,
55 #[serde(borrow)]
56 c: Cow<'a, str>,
57 d: u8,
58 #[serde(borrow)]
59 e: Cow<'a, str>,
60 f: char,
61 }
62
63 #[make_varule(MultiFieldConsecutiveStructULE)]
64 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, serde::Serialize, serde::Deserialize)]
65 #[zerovec::derive(Serialize, Deserialize, Debug)]
66 #[zerovec::format(zerovec::vecs::Index8)]
67 struct MultiFieldConsecutiveStruct<'a> {
68 #[serde(borrow)]
69 a: Cow<'a, str>,
70 #[serde(borrow)]
71 b: Cow<'a, str>,
72 #[serde(borrow)]
73 c: Cow<'a, str>,
74 #[serde(borrow)]
75 d: Cow<'a, str>,
76 }
77
78 #[make_varule(CustomVarFieldULE)]
79 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, serde::Serialize, serde::Deserialize)]
80 #[zerovec::derive(Serialize, Deserialize, Debug)]
81 struct CustomVarField<'a> {
82 #[zerovec::varule(MultiFieldStructULE)]
83 #[serde(borrow)]
84 a: MultiFieldStruct<'a>,
85 b: u32,
86 }
87
88 #[make_varule(MultiFieldTupleULE)]
89 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, serde::Serialize, serde::Deserialize)]
90 #[zerovec::derive(Serialize, Deserialize, Debug)]
91 #[zerovec::format(zerovec::vecs::Index32)]
92 struct MultiFieldTuple<'a>(
93 u8,
94 char,
95 #[serde(borrow)] VarZeroVec<'a, str>,
96 #[serde(borrow)] VarZeroVec<'a, [u8]>,
97 #[serde(borrow)] Cow<'a, str>,
98 );
99
100 /// The `assert` function should have the body `|(stack, zero)| assert_eq!(stack, &U::zero_from(&zero))`
101 ///
102 /// We cannot do this internally because we technically need a different `U` with a shorter lifetime here
103 /// which would require some gnarly lifetime bounds and perhaps a Yoke dependency. This is just a test, so it's
104 /// not important to get this 100% perfect
assert_zerovec<T, U, F>(slice: &[U], assert: F) where T: ule::VarULE + ?Sized + serde::Serialize, U: ule::EncodeAsVarULE<T> + serde::Serialize, F: Fn(&U, &T), for<'a> Box<T>: serde::Deserialize<'a>, for<'a> &'a T: serde::Deserialize<'a>, T: PartialEq + Debug,105 fn assert_zerovec<T, U, F>(slice: &[U], assert: F)
106 where
107 T: ule::VarULE + ?Sized + serde::Serialize,
108 U: ule::EncodeAsVarULE<T> + serde::Serialize,
109 F: Fn(&U, &T),
110 for<'a> Box<T>: serde::Deserialize<'a>,
111 for<'a> &'a T: serde::Deserialize<'a>,
112 T: PartialEq + Debug,
113 {
114 let varzerovec: VarZeroVec<T> = slice.into();
115
116 assert_eq!(varzerovec.len(), slice.len());
117
118 for (stack, zero) in slice.iter().zip(varzerovec.iter()) {
119 assert(stack, zero)
120 }
121
122 let bytes = varzerovec.as_bytes();
123 let name = std::any::type_name::<T>();
124 let reparsed: VarZeroVec<T> = VarZeroVec::parse_bytes(bytes)
125 .unwrap_or_else(|_| panic!("Parsing VarZeroVec<{name}> should succeed"));
126
127 assert_eq!(reparsed.len(), slice.len());
128
129 for (stack, zero) in slice.iter().zip(reparsed.iter()) {
130 assert(stack, zero)
131 }
132
133 let bincode = bincode::serialize(&varzerovec).unwrap();
134 let deserialized: VarZeroVec<T> = bincode::deserialize(&bincode).unwrap();
135
136 for (stack, zero) in slice.iter().zip(deserialized.iter()) {
137 assert(stack, zero)
138 }
139
140 let json_slice = serde_json::to_string(&slice).unwrap();
141 let json_vzv = serde_json::to_string(&varzerovec).unwrap();
142
143 assert_eq!(json_slice, json_vzv);
144
145 let deserialized: VarZeroVec<T> = serde_json::from_str(&json_vzv).unwrap();
146
147 for (stack, zero) in slice.iter().zip(deserialized.iter()) {
148 assert(stack, zero)
149 }
150
151 if let Some(first) = varzerovec.get(0) {
152 let bincode = bincode::serialize(first).unwrap();
153 let deserialized: &T = bincode::deserialize(&bincode).unwrap();
154 let deserialized_box: Box<T> = bincode::deserialize(&bincode).unwrap();
155 assert_eq!(
156 first, deserialized,
157 "Single element roundtrips with bincode"
158 );
159 assert_eq!(
160 first, &*deserialized_box,
161 "Single element roundtrips with bincode"
162 );
163
164 let json = serde_json::to_string(first).unwrap();
165 let deserialized: Box<T> = serde_json::from_str(&json).unwrap();
166 assert_eq!(
167 first, &*deserialized,
168 "Single element roundtrips with serde"
169 );
170 }
171 }
172
main()173 fn main() {
174 assert_zerovec::<VarStructULE, VarStruct, _>(TEST_VARSTRUCTS, |stack, zero| {
175 assert_eq!(stack, &VarStruct::zero_from(zero))
176 });
177
178 assert_zerovec::<MultiFieldStructULE, MultiFieldStruct, _>(TEST_MULTIFIELD, |stack, zero| {
179 assert_eq!(stack, &MultiFieldStruct::zero_from(zero))
180 });
181
182 assert_zerovec::<MultiFieldConsecutiveStructULE, MultiFieldConsecutiveStruct, _>(
183 TEST_MULTICONSECUTIVE,
184 |stack, zero| assert_eq!(stack, &MultiFieldConsecutiveStruct::zero_from(zero)),
185 );
186
187 let vartuples = &[
188 VarTupleStruct(101, 'ø', TEST_STRINGS1.into()),
189 VarTupleStruct(9499, '⸘', TEST_STRINGS2.into()),
190 VarTupleStruct(3478, '月', TEST_STRINGS3.into()),
191 ];
192 assert_zerovec::<VarTupleStructULE, VarTupleStruct, _>(vartuples, |stack, zero| {
193 assert_eq!(stack, &VarTupleStruct::zero_from(zero))
194 });
195
196 // Test that all fields are accessible on a type using multifieldule
197 let multi_ule = ule::encode_varule_to_box(&TEST_MULTIFIELD[0]);
198 assert_eq!(multi_ule.a, TEST_MULTIFIELD[0].a.to_unaligned());
199 assert_eq!(multi_ule.b, TEST_MULTIFIELD[0].b.to_unaligned());
200 assert_eq!(multi_ule.c(), TEST_MULTIFIELD[0].c);
201 assert_eq!(multi_ule.d, TEST_MULTIFIELD[0].d);
202 assert_eq!(multi_ule.e(), TEST_MULTIFIELD[0].e);
203 assert_eq!(multi_ule.f, TEST_MULTIFIELD[0].f.to_unaligned());
204 }
205
206 const TEST_VARSTRUCTS: &[VarStruct<'static>] = &[
207 VarStruct {
208 a: 101,
209 b: 'ø',
210 c: Cow::Borrowed("testīng strīng"),
211 },
212 VarStruct {
213 a: 9499,
214 b: '⸘',
215 c: Cow::Borrowed("a diffərənt ştring"),
216 },
217 VarStruct {
218 a: 3478,
219 b: '月',
220 c: Cow::Borrowed("好多嘅 string"),
221 },
222 ];
223
224 const TEST_STRINGS1: &[&str] = &["foo", "bar", "baz"];
225 const TEST_STRINGS2: &[&str] = &["hellø", "wørłd"];
226 const TEST_STRINGS3: &[&str] = &["łořem", "ɨpsu₥"];
227
228 const TEST_MULTIFIELD: &[MultiFieldStruct<'static>] = &[
229 MultiFieldStruct {
230 a: 101,
231 b: 'ø',
232 c: Cow::Borrowed("testīng strīng"),
233 d: 8,
234 e: Cow::Borrowed("another testīng strīng"),
235 f: 'å',
236 },
237 MultiFieldStruct {
238 a: 9499,
239 b: '⸘',
240 c: Cow::Borrowed("a diffərənt ştring"),
241 d: 120,
242 e: Cow::Borrowed("a diffərənt testing ştring"),
243 f: 'ł',
244 },
245 MultiFieldStruct {
246 a: 3478,
247 b: '月',
248 c: Cow::Borrowed("好多嘅 string"),
249 d: 89,
250 e: Cow::Borrowed("many 好多嘅 string"),
251 f: 'ə',
252 },
253 ];
254
255 const TEST_MULTICONSECUTIVE: &[MultiFieldConsecutiveStruct<'static>] =
256 &[MultiFieldConsecutiveStruct {
257 a: Cow::Borrowed("one"),
258 b: Cow::Borrowed("2"),
259 c: Cow::Borrowed("three"),
260 d: Cow::Borrowed("four"),
261 }];
262