Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ULE types Copy, add PairULE #1193

Merged
merged 7 commits into from
Oct 20, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions components/datetime/src/fields/ule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ impl AsULE for fields::Field {
type ULE = FieldULE;

#[inline]
fn as_unaligned(&self) -> Self::ULE {
fn as_unaligned(self) -> Self::ULE {
FieldULE([self.symbol.idx(), self.length.idx()])
}

#[inline]
fn from_unaligned(unaligned: &Self::ULE) -> Self {
fn from_unaligned(unaligned: Self::ULE) -> Self {
let value = unaligned.0;
let symbol = fields::FieldSymbol::from_idx(value[0]).unwrap();
let length = fields::FieldLength::from_idx(value[1]).unwrap();
Expand Down Expand Up @@ -119,7 +119,7 @@ mod test {
for (ref_field, ref_bytes) in samples {
let ule = ref_field.as_unaligned();
assert_eq!(ULE::as_byte_slice(&[ule]), *ref_bytes);
let field = Field::from_unaligned(&ule);
let field = Field::from_unaligned(ule);
assert_eq!(field, *ref_field);
}
}
Expand Down
18 changes: 9 additions & 9 deletions components/datetime/src/pattern/item/ule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,21 +107,21 @@ impl AsULE for PatternItem {
type ULE = PatternItemULE;

#[inline]
fn as_unaligned(&self) -> Self::ULE {
fn as_unaligned(self) -> Self::ULE {
match self {
Self::Field(field) => {
PatternItemULE([0b1000_0000, field.symbol.idx(), field.length.idx()])
}
Self::Literal(ch) => {
let u = *ch as u32;
let u = ch as u32;
let bytes = u.to_be_bytes();
PatternItemULE([bytes[1], bytes[2], bytes[3]])
}
}
}

#[inline]
fn from_unaligned(unaligned: &Self::ULE) -> Self {
fn from_unaligned(unaligned: Self::ULE) -> Self {
let value = unaligned.0;
match PatternItemULE::determine_field_from_u8(value[0]) {
false => {
Expand Down Expand Up @@ -238,19 +238,19 @@ impl AsULE for GenericPatternItem {
type ULE = GenericPatternItemULE;

#[inline]
fn as_unaligned(&self) -> Self::ULE {
fn as_unaligned(self) -> Self::ULE {
match self {
Self::Placeholder(idx) => GenericPatternItemULE([0b1000_0000, 0x00, *idx]),
Self::Placeholder(idx) => GenericPatternItemULE([0b1000_0000, 0x00, idx]),
Self::Literal(ch) => {
let u = *ch as u32;
let u = ch as u32;
let bytes = u.to_be_bytes();
GenericPatternItemULE([bytes[1], bytes[2], bytes[3]])
}
}
}

#[inline]
fn from_unaligned(unaligned: &Self::ULE) -> Self {
fn from_unaligned(unaligned: Self::ULE) -> Self {
let value = unaligned.0;
match GenericPatternItemULE::determine_field_from_u8(value[0]) {
false => {
Expand Down Expand Up @@ -305,7 +305,7 @@ mod test {
for (ref_pattern, ref_bytes) in samples {
let ule = ref_pattern.as_unaligned();
assert_eq!(ULE::as_byte_slice(&[ule]), *ref_bytes);
let pattern = PatternItem::from_unaligned(&ule);
let pattern = PatternItem::from_unaligned(ule);
assert_eq!(pattern, *ref_pattern);
}
}
Expand Down Expand Up @@ -361,7 +361,7 @@ mod test {
for (ref_pattern, ref_bytes) in samples {
let ule = ref_pattern.as_unaligned();
assert_eq!(ULE::as_byte_slice(&[ule]), *ref_bytes);
let pattern = GenericPatternItem::from_unaligned(&ule);
let pattern = GenericPatternItem::from_unaligned(ule);
assert_eq!(pattern, *ref_pattern);
}
}
Expand Down
10 changes: 5 additions & 5 deletions components/properties/src/ule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ impl AsULE for GeneralSubcategory {
type ULE = GeneralSubcategoryULE;

#[inline]
fn as_unaligned(&self) -> Self::ULE {
let u = *self as u8;
fn as_unaligned(self) -> Self::ULE {
let u = self as u8;
GeneralSubcategoryULE(u)
}

#[inline]
fn from_unaligned(unaligned: &Self::ULE) -> Self {
fn from_unaligned(unaligned: Self::ULE) -> Self {
// Safe because the contents of GeneralSubcategoryULE are required to be valid.
unsafe { Self::from_unchecked(unaligned.0) }
}
Expand Down Expand Up @@ -50,12 +50,12 @@ impl AsULE for Script {
type ULE = PlainOldULE<2>;

#[inline]
fn as_unaligned(&self) -> Self::ULE {
fn as_unaligned(self) -> Self::ULE {
PlainOldULE(self.0.to_le_bytes())
}

#[inline]
fn from_unaligned(unaligned: &Self::ULE) -> Self {
fn from_unaligned(unaligned: Self::ULE) -> Self {
Script(u16::from_le_bytes(unaligned.0))
}
}
13 changes: 7 additions & 6 deletions utils/uniset/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ impl UnicodeSetBuilder {
.chunks(2)
.for_each(|pair| {
self.add(
AsULE::from_unaligned(&pair[0]),
AsULE::from_unaligned(&pair[1]),
AsULE::from_unaligned(pair[0]),
AsULE::from_unaligned(pair[1]),
)
});
}
Expand Down Expand Up @@ -246,8 +246,8 @@ impl UnicodeSetBuilder {
.chunks(2)
.for_each(|pair| {
self.remove(
AsULE::from_unaligned(&pair[0]),
AsULE::from_unaligned(&pair[1]),
AsULE::from_unaligned(pair[0]),
AsULE::from_unaligned(pair[1]),
)
});
}
Expand Down Expand Up @@ -311,8 +311,8 @@ impl UnicodeSetBuilder {
pub fn retain_set(&mut self, set: &UnicodeSet) {
let mut prev = 0;
for pair in set.as_inversion_list().as_slice().chunks(2) {
let range_start = AsULE::from_unaligned(&pair[0]);
let range_limit = AsULE::from_unaligned(&pair[1]);
let range_start = AsULE::from_unaligned(pair[0]);
let range_limit = AsULE::from_unaligned(pair[1]);
self.remove(prev, range_start);
prev = range_limit;
}
Expand Down Expand Up @@ -449,6 +449,7 @@ impl UnicodeSetBuilder {
.as_inversion_list()
.as_slice()
.iter()
.copied()
.map(|cp| <u32 as AsULE>::from_unaligned(cp));
self.complement_list(inv_list_iter_owned);
}
Expand Down
10 changes: 5 additions & 5 deletions utils/uniset/src/uniset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ impl<'data> UnicodeSet<'data> {
.as_slice()
.chunks(2)
.map(|end_points| {
<u32 as AsULE>::from_unaligned(&end_points[1])
- <u32 as AsULE>::from_unaligned(&end_points[0])
<u32 as AsULE>::from_unaligned(end_points[1])
- <u32 as AsULE>::from_unaligned(end_points[0])
})
.sum::<u32>() as usize;
Ok(Self { inv_list, size })
Expand Down Expand Up @@ -264,7 +264,7 @@ impl<'data> UnicodeSet<'data> {
self.inv_list
.as_slice()
.chunks(2)
.flat_map(|pair| (AsULE::from_unaligned(&pair[0])..AsULE::from_unaligned(&pair[1])))
.flat_map(|pair| (AsULE::from_unaligned(pair[0])..AsULE::from_unaligned(pair[1])))
.filter_map(char::from_u32)
}

Expand All @@ -288,8 +288,8 @@ impl<'data> UnicodeSet<'data> {
/// ```
pub fn iter_ranges(&self) -> impl ExactSizeIterator<Item = RangeInclusive<u32>> + '_ {
self.inv_list.as_slice().chunks(2).map(|pair| {
let range_start: u32 = AsULE::from_unaligned(&pair[0]);
let range_limit: u32 = AsULE::from_unaligned(&pair[1]);
let range_start: u32 = AsULE::from_unaligned(pair[0]);
let range_limit: u32 = AsULE::from_unaligned(pair[1]);
RangeInclusive::new(range_start, range_limit - 1)
})
}
Expand Down
5 changes: 2 additions & 3 deletions utils/uniset/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@ pub fn is_valid_zv(inv_list_zv: &ZeroVec<'_, u32>) -> bool {
slice.is_empty()
|| (slice.len() % 2 == 0
&& slice.windows(2).all(|chunk| {
<u32 as AsULE>::from_unaligned(&chunk[0])
< <u32 as AsULE>::from_unaligned(&chunk[1])
<u32 as AsULE>::from_unaligned(chunk[0]) < <u32 as AsULE>::from_unaligned(chunk[1])
})
&& slice.last().map_or(false, |e| {
<u32 as AsULE>::from_unaligned(e) <= ((char::MAX as u32) + 1)
<u32 as AsULE>::from_unaligned(*e) <= ((char::MAX as u32) + 1)
}))
}

Expand Down
4 changes: 2 additions & 2 deletions utils/zerovec/src/map/kv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ macro_rules! impl_sized_kv {

#[inline]
fn cmp_get(&self, g: &Self::GetType) -> Ordering {
self.cmp(&$ty::from_unaligned(g))
self.cmp(&$ty::from_unaligned(*g))
}

#[inline]
fn with_ser<R>(g: &Self::GetType, f: impl FnOnce(&Self) -> R) -> R {
f(&Self::from_unaligned(g))
f(&Self::from_unaligned(*g))
}

#[inline]
Expand Down
6 changes: 3 additions & 3 deletions utils/zerovec/src/map/vecs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ where
self.to_mut().insert(index, value.as_unaligned())
}
fn remove(&mut self, index: usize) -> T {
T::from_unaligned(&self.to_mut().remove(index))
T::from_unaligned(self.to_mut().remove(index))
}
fn replace(&mut self, index: usize, value: &T) -> T {
let vec = self.to_mut();
T::from_unaligned(&mem::replace(&mut vec[index], value.as_unaligned()))
T::from_unaligned(mem::replace(&mut vec[index], value.as_unaligned()))
}
fn push(&mut self, value: &T) {
self.to_mut().push(value.as_unaligned())
Expand All @@ -96,7 +96,7 @@ where
fn is_ascending(&self) -> bool {
self.as_slice()
.windows(2)
.all(|w| T::from_unaligned(&w[1]).cmp(&T::from_unaligned(&w[0])) == Ordering::Greater)
.all(|w| T::from_unaligned(w[1]).cmp(&T::from_unaligned(w[0])) == Ordering::Greater)
}
}

Expand Down
34 changes: 25 additions & 9 deletions utils/zerovec/src/ule/chars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use core::convert::TryFrom;
/// let c1 = '𑄃';
/// let ule = c1.as_unaligned();
/// assert_eq!(CharULE::as_byte_slice(&[ule]), &[0x03, 0x11, 0x01, 0x00]);
/// let c2 = char::from_unaligned(&ule);
/// let c2 = char::from_unaligned(ule);
/// assert_eq!(c1, c2);
/// ```
///
Expand Down Expand Up @@ -66,13 +66,13 @@ impl AsULE for char {
type ULE = CharULE;

#[inline]
fn as_unaligned(&self) -> Self::ULE {
let u = u32::from(*self);
fn as_unaligned(self) -> Self::ULE {
let u = u32::from(self);
CharULE(u.to_le_bytes())
}

#[inline]
fn from_unaligned(unaligned: &Self::ULE) -> Self {
fn from_unaligned(unaligned: Self::ULE) -> Self {
let u = u32::from_le_bytes(unaligned.0);
// Safe because the bytes of CharULE are defined to represent a valid Unicode code point.
// TODO: Use char::from_u32_unchecked() when stabilized
Expand All @@ -92,13 +92,17 @@ mod test {
fn test_parse() {
// 1-byte, 2-byte, 3-byte, and 4-byte character in UTF-8 (not as relevant in UTF-32)
let chars = ['w', 'ω', '文', '𑄃'];
let char_ules: Vec<CharULE> = chars.iter().map(char::as_unaligned).collect();
let char_ules: Vec<CharULE> = chars.iter().copied().map(char::as_unaligned).collect();
let char_bytes: &[u8] = CharULE::as_byte_slice(&char_ules);

// Check parsing
let parsed_ules: &[CharULE] = CharULE::parse_byte_slice(char_bytes).unwrap();
assert_eq!(char_ules, parsed_ules);
let parsed_chars: Vec<char> = parsed_ules.iter().map(char::from_unaligned).collect();
let parsed_chars: Vec<char> = parsed_ules
.iter()
.copied()
.map(char::from_unaligned)
.collect();
assert_eq!(&chars, parsed_chars.as_slice());

// Check EqULE
Expand All @@ -110,7 +114,11 @@ mod test {

// Compare to u32
let u32s: Vec<u32> = chars.iter().copied().map(u32::from).collect();
let u32_ules: Vec<PlainOldULE<4>> = u32s.iter().map(<u32 as AsULE>::as_unaligned).collect();
let u32_ules: Vec<PlainOldULE<4>> = u32s
.iter()
.copied()
.map(<u32 as AsULE>::as_unaligned)
.collect();
let u32_bytes: &[u8] = PlainOldULE::<4>::as_byte_slice(&u32_ules);
assert_eq!(char_bytes, u32_bytes);

Expand All @@ -125,14 +133,22 @@ mod test {
fn test_failures() {
// 119 and 120 are valid, but not 0xD800 (high surrogate)
let u32s = [119, 0xD800, 120];
let u32_ules: Vec<PlainOldULE<4>> = u32s.iter().map(<u32 as AsULE>::as_unaligned).collect();
let u32_ules: Vec<PlainOldULE<4>> = u32s
.iter()
.copied()
.map(<u32 as AsULE>::as_unaligned)
.collect();
let u32_bytes: &[u8] = PlainOldULE::<4>::as_byte_slice(&u32_ules);
let parsed_ules_result = CharULE::parse_byte_slice(u32_bytes);
assert!(matches!(parsed_ules_result, Err(_)));

// 0x20FFFF is out of range for a char
let u32s = [0x20FFFF];
let u32_ules: Vec<PlainOldULE<4>> = u32s.iter().map(<u32 as AsULE>::as_unaligned).collect();
let u32_ules: Vec<PlainOldULE<4>> = u32s
.iter()
.copied()
.map(<u32 as AsULE>::as_unaligned)
.collect();
let u32_bytes: &[u8] = PlainOldULE::<4>::as_byte_slice(&u32_ules);
let parsed_ules_result = CharULE::parse_byte_slice(u32_bytes);
assert!(matches!(parsed_ules_result, Err(_)));
Expand Down
8 changes: 4 additions & 4 deletions utils/zerovec/src/ule/custom/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@
//!
//! let vzv = VarZeroVec::from(&*foos);
//!
//! assert_eq!(char::from_unaligned(&vzv.get(0).unwrap().field1), 'u');
//! assert_eq!(u32::from_unaligned(&vzv.get(0).unwrap().field2), 983);
//! assert_eq!(char::from_unaligned(vzv.get(0).unwrap().field1), 'u');
//! assert_eq!(u32::from_unaligned(vzv.get(0).unwrap().field2), 983);
//! assert_eq!(&vzv.get(0).unwrap().field3, ZeroVec::clone_from_slice(&[1212,2309,500,7000]).as_slice());
//!
//! assert_eq!(char::from_unaligned(&vzv.get(1).unwrap().field1), 'l');
//! assert_eq!(u32::from_unaligned(&vzv.get(1).unwrap().field2), 1010);
//! assert_eq!(char::from_unaligned(vzv.get(1).unwrap().field1), 'l');
//! assert_eq!(u32::from_unaligned(vzv.get(1).unwrap().field2), 1010);
//! assert_eq!(&vzv.get(1).unwrap().field3, ZeroVec::clone_from_slice(&[1932, 0, 8888, 91237]).as_slice());
//! }
//! ```
Expand Down
10 changes: 6 additions & 4 deletions utils/zerovec/src/ule/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
mod chars;
pub mod custom;
mod error;
mod pair;
mod plain;
mod string;
mod vec;

pub use chars::CharULE;
pub use error::ULEError;
pub use pair::{PairULE, PairULEError};
pub use plain::PlainOldULE;

use alloc::alloc::Layout;
Expand Down Expand Up @@ -56,7 +58,7 @@ use core::{fmt, mem, slice};
pub unsafe trait ULE
where
Self: Sized,
Self: 'static,
Self: Copy + 'static,
{
/// The error that occurs if a byte array is not valid for this ULE.
type Error: fmt::Display;
Expand Down Expand Up @@ -136,7 +138,7 @@ where
}

/// A trait for any type that has a 1:1 mapping with an unaligned little-endian (ULE) type.
pub trait AsULE {
pub trait AsULE: Copy {
/// The ULE type corresponding to `Self`.
///
/// Types having infallible conversions from all bit values (Plain Old Data) can use
Expand All @@ -150,7 +152,7 @@ pub trait AsULE {
/// This function may involve byte order swapping (native-endian to little-endian).
///
/// For best performance, mark your implementation of this function `#[inline]`.
fn as_unaligned(&self) -> Self::ULE;
fn as_unaligned(self) -> Self::ULE;

/// Converts from `&Self::ULE` to `Self`.
///
Expand All @@ -163,7 +165,7 @@ pub trait AsULE {
/// This function is infallible because bit validation should have occurred when `Self::ULE`
/// was first constructed. An implementation may therefore involve an `unsafe{}` block, like
/// `from_bytes_unchecked()`.
fn from_unaligned(unaligned: &Self::ULE) -> Self;
fn from_unaligned(unaligned: Self::ULE) -> Self;
}

/// An [`EqULE`] type is one whose byte sequence equals the byte sequence of its ULE type on
Expand Down
Loading