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 zerovec::ule::AsULE;
6 use zerovec::ule::EncodeAsVarULE;
7 use zerovec::*;
8
9 #[repr(C, packed)]
10 #[derive(ule::ULE, Copy, Clone)]
11 pub struct FooULE {
12 a: u8,
13 b: <u32 as AsULE>::ULE,
14 c: <char as AsULE>::ULE,
15 }
16
17 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
18 struct Foo {
19 a: u8,
20 b: u32,
21 c: char,
22 }
23
24 impl AsULE for Foo {
25 type ULE = FooULE;
to_unaligned(self) -> FooULE26 fn to_unaligned(self) -> FooULE {
27 FooULE {
28 a: self.a,
29 b: self.b.to_unaligned(),
30 c: self.c.to_unaligned(),
31 }
32 }
33
from_unaligned(other: FooULE) -> Self34 fn from_unaligned(other: FooULE) -> Self {
35 Self {
36 a: other.a,
37 b: AsULE::from_unaligned(other.b),
38 c: AsULE::from_unaligned(other.c),
39 }
40 }
41 }
42
43 #[repr(C, packed)]
44 #[derive(ule::VarULE)]
45 pub struct RelationULE {
46 /// This maps to (AndOr, Polarity, Operand),
47 /// with the first bit mapping to AndOr (1 == And), the second bit
48 /// to Polarity (1 == Positive), and the remaining bits to Operand
49 /// encoded via Operand::encode. It is unsound for the Operand bits to
50 /// not be a valid encoded Operand.
51 andor_polarity_operand: u8,
52 modulo: <u32 as AsULE>::ULE,
53 range_list: ZeroSlice<Foo>,
54 }
55
56 #[derive(Clone, PartialEq, Debug)]
57 pub struct Relation<'a> {
58 andor_polarity_operand: u8,
59 modulo: u32,
60 range_list: ZeroVec<'a, Foo>,
61 }
62
63 unsafe impl EncodeAsVarULE<RelationULE> for Relation<'_> {
encode_var_ule_as_slices<R>(&self, cb: impl FnOnce(&[&[u8]]) -> R) -> R64 fn encode_var_ule_as_slices<R>(&self, cb: impl FnOnce(&[&[u8]]) -> R) -> R {
65 cb(&[
66 &[self.andor_polarity_operand],
67 ule::ULE::slice_as_bytes(&[self.modulo.to_unaligned()]),
68 self.range_list.as_bytes(),
69 ])
70 }
71 }
72
73 impl RelationULE {
as_relation(&self) -> Relation74 pub fn as_relation(&self) -> Relation {
75 Relation {
76 andor_polarity_operand: self.andor_polarity_operand,
77 modulo: u32::from_unaligned(self.modulo),
78 range_list: self.range_list.as_zerovec(),
79 }
80 }
81 }
82
83 const TEST_SLICE: &[Foo] = &[
84 Foo {
85 a: 101,
86 b: 924,
87 c: '⸘',
88 },
89 Foo {
90 a: 217,
91 b: 4228,
92 c: 'ə',
93 },
94 Foo {
95 a: 117,
96 b: 9090,
97 c: 'ø',
98 },
99 ];
100
101 const TEST_SLICE2: &[Foo] = &[
102 Foo {
103 a: 92,
104 b: 4,
105 c: 'å',
106 },
107 Foo {
108 a: 9,
109 b: 49993,
110 c: '±',
111 },
112 ];
test_zerovec()113 fn test_zerovec() {
114 let zerovec: ZeroVec<Foo> = TEST_SLICE.iter().copied().collect();
115
116 assert_eq!(zerovec, TEST_SLICE);
117
118 let bytes = zerovec.as_bytes();
119 let reparsed: ZeroVec<Foo> = ZeroVec::parse_bytes(bytes).expect("Parsing should succeed");
120
121 assert_eq!(reparsed, TEST_SLICE);
122 }
123
test_varzerovec()124 fn test_varzerovec() {
125 let relation1 = Relation {
126 andor_polarity_operand: 1,
127 modulo: 5004,
128 range_list: TEST_SLICE.iter().copied().collect(),
129 };
130 let relation2 = Relation {
131 andor_polarity_operand: 5,
132 modulo: 909,
133 range_list: TEST_SLICE2.iter().copied().collect(),
134 };
135
136 let relations = &[relation1, relation2];
137
138 let vzv = VarZeroVec::<_>::from(relations);
139
140 for (ule, stack) in vzv.iter().zip(relations.iter()) {
141 assert_eq!(*stack, ule.as_relation());
142 }
143
144 let bytes = vzv.as_bytes();
145
146 let recovered: VarZeroVec<RelationULE> =
147 VarZeroVec::parse_bytes(bytes).expect("Parsing should succeed");
148
149 for (ule, stack) in recovered.iter().zip(relations.iter()) {
150 assert_eq!(*stack, ule.as_relation());
151 }
152 }
153
main()154 fn main() {
155 test_zerovec();
156 test_varzerovec();
157 }
158