157 lines
3.6 KiB
Rust
157 lines
3.6 KiB
Rust
// This file is part of ICU4X. For terms of use, please see the file
|
|
// called LICENSE at the top level of the ICU4X source tree
|
|
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
|
|
|
|
use zerovec::ule::AsULE;
|
|
use zerovec::ule::EncodeAsVarULE;
|
|
use zerovec::*;
|
|
|
|
#[repr(C, packed)]
|
|
#[derive(ule::ULE, Copy, Clone)]
|
|
pub struct FooULE {
|
|
a: u8,
|
|
b: <u32 as AsULE>::ULE,
|
|
c: <char as AsULE>::ULE,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
struct Foo {
|
|
a: u8,
|
|
b: u32,
|
|
c: char,
|
|
}
|
|
|
|
impl AsULE for Foo {
|
|
type ULE = FooULE;
|
|
fn to_unaligned(self) -> FooULE {
|
|
FooULE {
|
|
a: self.a,
|
|
b: self.b.to_unaligned(),
|
|
c: self.c.to_unaligned(),
|
|
}
|
|
}
|
|
|
|
fn from_unaligned(other: FooULE) -> Self {
|
|
Self {
|
|
a: other.a,
|
|
b: AsULE::from_unaligned(other.b),
|
|
c: AsULE::from_unaligned(other.c),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[repr(C, packed)]
|
|
#[derive(ule::VarULE)]
|
|
pub struct RelationULE {
|
|
/// This maps to (AndOr, Polarity, Operand),
|
|
/// with the first bit mapping to AndOr (1 == And), the second bit
|
|
/// to Polarity (1 == Positive), and the remaining bits to Operand
|
|
/// encoded via Operand::encode. It is unsound for the Operand bits to
|
|
/// not be a valid encoded Operand.
|
|
andor_polarity_operand: u8,
|
|
modulo: <u32 as AsULE>::ULE,
|
|
range_list: ZeroSlice<Foo>,
|
|
}
|
|
|
|
#[derive(Clone, PartialEq, Debug)]
|
|
pub struct Relation<'a> {
|
|
andor_polarity_operand: u8,
|
|
modulo: u32,
|
|
range_list: ZeroVec<'a, Foo>,
|
|
}
|
|
|
|
unsafe impl EncodeAsVarULE<RelationULE> for Relation<'_> {
|
|
fn encode_var_ule_as_slices<R>(&self, cb: impl FnOnce(&[&[u8]]) -> R) -> R {
|
|
cb(&[
|
|
&[self.andor_polarity_operand],
|
|
ule::ULE::as_byte_slice(&[self.modulo.to_unaligned()]),
|
|
self.range_list.as_bytes(),
|
|
])
|
|
}
|
|
}
|
|
|
|
impl RelationULE {
|
|
pub fn as_relation(&self) -> Relation {
|
|
Relation {
|
|
andor_polarity_operand: self.andor_polarity_operand,
|
|
modulo: u32::from_unaligned(self.modulo),
|
|
range_list: self.range_list.as_zerovec(),
|
|
}
|
|
}
|
|
}
|
|
|
|
const TEST_SLICE: &[Foo] = &[
|
|
Foo {
|
|
a: 101,
|
|
b: 924,
|
|
c: '⸘',
|
|
},
|
|
Foo {
|
|
a: 217,
|
|
b: 4228,
|
|
c: 'ə',
|
|
},
|
|
Foo {
|
|
a: 117,
|
|
b: 9090,
|
|
c: 'ø',
|
|
},
|
|
];
|
|
|
|
const TEST_SLICE2: &[Foo] = &[
|
|
Foo {
|
|
a: 92,
|
|
b: 4,
|
|
c: 'å',
|
|
},
|
|
Foo {
|
|
a: 9,
|
|
b: 49993,
|
|
c: '±',
|
|
},
|
|
];
|
|
fn test_zerovec() {
|
|
let zerovec: ZeroVec<Foo> = TEST_SLICE.iter().copied().collect();
|
|
|
|
assert_eq!(zerovec, TEST_SLICE);
|
|
|
|
let bytes = zerovec.as_bytes();
|
|
let reparsed: ZeroVec<Foo> = ZeroVec::parse_byte_slice(bytes).expect("Parsing should succeed");
|
|
|
|
assert_eq!(reparsed, TEST_SLICE);
|
|
}
|
|
|
|
fn test_varzerovec() {
|
|
let relation1 = Relation {
|
|
andor_polarity_operand: 1,
|
|
modulo: 5004,
|
|
range_list: TEST_SLICE.iter().copied().collect(),
|
|
};
|
|
let relation2 = Relation {
|
|
andor_polarity_operand: 5,
|
|
modulo: 909,
|
|
range_list: TEST_SLICE2.iter().copied().collect(),
|
|
};
|
|
|
|
let relations = &[relation1, relation2];
|
|
|
|
let vzv = VarZeroVec::<_>::from(relations);
|
|
|
|
for (ule, stack) in vzv.iter().zip(relations.iter()) {
|
|
assert_eq!(*stack, ule.as_relation());
|
|
}
|
|
|
|
let bytes = vzv.as_bytes();
|
|
|
|
let recovered: VarZeroVec<RelationULE> =
|
|
VarZeroVec::parse_byte_slice(bytes).expect("Parsing should succeed");
|
|
|
|
for (ule, stack) in recovered.iter().zip(relations.iter()) {
|
|
assert_eq!(*stack, ule.as_relation());
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
test_zerovec();
|
|
test_varzerovec();
|
|
}
|