• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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