• 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 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