From d043e459505ee186c1101ae634aa7b7ebeec9ae8 Mon Sep 17 00:00:00 2001 From: Niels Saurer Date: Thu, 25 May 2023 13:56:55 +0200 Subject: [PATCH 1/8] add macro --- utils/zerovec/src/zerovec/mod.rs | 81 ++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/utils/zerovec/src/zerovec/mod.rs b/utils/zerovec/src/zerovec/mod.rs index 848ee0ffd5d..9f1c439cd4f 100644 --- a/utils/zerovec/src/zerovec/mod.rs +++ b/utils/zerovec/src/zerovec/mod.rs @@ -919,6 +919,87 @@ impl FromIterator for ZeroVec<'_, T> { } } +/// Convenience wrapper for [`ZeroSlice::from_ule_slice`]. The value will be created at compile-time. +/// +/// # Arguments +/// +/// * `$aligned` - The type of an element in its canonical, aligned form, e.g., `char`. +/// * `$array_fn` - A const function that converts an array of `$aligned` elements into an array +/// of their unaligned equivalents, e.g., +/// `const fn from_array(arr: [char; N]) -> [::ULE; N]`. +/// * `$x` - The elements that the `ZeroSlice` will hold. +/// +/// # Examples +/// +/// Using array-conversion functions provided by this crate: +/// +/// ``` +/// use zerovec::{ZeroSlice, zeroslice, ule::AsULE}; +/// +/// const SIGNATURE: &ZeroSlice = zeroslice![char; ::ULE::from_array; 'b', 'y', 'e', '✌']; +/// const EMPTY: &ZeroSlice = zeroslice![]; +/// let empty: &ZeroSlice = zeroslice![]; +/// let nums = zeroslice![u32; ::ULE::from_array; 1, 2, 3, 4, 5]; +/// assert_eq!(nums.last().unwrap(), 5); +/// ``` +/// +/// Using a custom array-conversion function: +/// +/// ``` +/// use zerovec::{ZeroSlice, zeroslice}; +/// +/// mod conversion { +/// use zerovec::ule::RawBytesULE; +/// pub(super) const fn i16_array_to_be_array(arr: [i16; N]) -> [RawBytesULE<2>; N] { +/// let mut result = [RawBytesULE([0; 2]); N]; +/// let mut i = 0; +/// while i < N { +/// result[i] = RawBytesULE(arr[i].to_be_bytes()); +/// i += 1; +/// } +/// result +/// } +/// } +/// +/// const NUMBERS: &ZeroSlice = zeroslice![i16; conversion::i16_array_to_be_array; 1, -2, 3, -4, 5]; +/// ``` +#[macro_export] +macro_rules! zeroslice { + () => ( + $crate::ZeroSlice::new_empty() + ); + ($aligned:ty; $array_fn:expr; $($x:expr),+ $(,)?) => ( + $crate::ZeroSlice::<$aligned>::from_ule_slice( + {const X: &[<$aligned as $crate::ule::AsULE>::ULE] = &$array_fn([$($x),+]); X} + ) + ); +} + +/// Creates a borrowed `ZeroVec`. Convenience wrapper for `zeroslice![...].as_zerovec()`. +/// +/// See [`zeroslice!`](crate::zeroslice) for more information. +/// +/// # Examples +/// +/// ``` +/// use zerovec::{ZeroVec, zerovec, ule::AsULE}; +/// +/// const SIGNATURE: ZeroVec = zerovec![char; ::ULE::from_array; 'a', 'y', 'e', '✌']; +/// assert!(!SIGNATURE.is_owned()); +/// +/// const EMPTY: ZeroVec = zerovec![]; +/// assert!(!EMPTY.is_owned()); +/// ``` +#[macro_export] +macro_rules! zerovec { + () => ( + $crate::ZeroVec::new() + ); + ($aligned:ty; $array_fn:expr; $($x:expr),+ $(,)?) => ( + $crate::zeroslice![$aligned; $array_fn; $($x),+].as_zerovec() + ); +} + #[cfg(test)] mod tests { use super::*; From 5d01ee5ff0f80cb0a8ccd9401c5ac61c17dfd963 Mon Sep 17 00:00:00 2001 From: Niels Saurer Date: Thu, 25 May 2023 17:16:45 +0200 Subject: [PATCH 2/8] replace usages of from_ule_slice with macro --- components/collator/src/elements.rs | 14 +++++--------- components/collator/src/provider.rs | 7 +++---- .../collections/src/codepointinvlist/cpinvlist.rs | 9 +++------ .../src/codepointtrie/benches/tries/gc_fast.rs | 7 ++++--- .../src/codepointtrie/benches/tries/gc_small.rs | 7 ++++--- components/normalizer/src/lib.rs | 8 +++----- utils/zerovec/src/zerovec/slice.rs | 14 +++++--------- 7 files changed, 27 insertions(+), 39 deletions(-) diff --git a/components/collator/src/elements.rs b/components/collator/src/elements.rs index 08934ad383d..7e32578a2c6 100644 --- a/components/collator/src/elements.rs +++ b/components/collator/src/elements.rs @@ -27,7 +27,7 @@ use icu_properties::CanonicalCombiningClass; use smallvec::SmallVec; use zerovec::ule::AsULE; use zerovec::ule::RawBytesULE; -use zerovec::ZeroSlice; +use zerovec::{zeroslice, ZeroSlice}; use crate::provider::CollationDataV1; @@ -147,17 +147,13 @@ pub(crate) const FFFD_CE: CollationElement = CollationElement(FFFD_CE_VALUE); pub(crate) const FFFD_CE32_VALUE: u32 = 0xFFFD0505; pub(crate) const FFFD_CE32: CollationElement32 = CollationElement32(FFFD_CE32_VALUE); -pub(crate) const EMPTY_U16: &ZeroSlice = - ZeroSlice::::from_ule_slice(&::ULE::from_array([])); +pub(crate) const EMPTY_U16: &ZeroSlice = zeroslice![]; const SINGLE_REPLACEMENT_CHARACTER_U16: &ZeroSlice = - ZeroSlice::::from_ule_slice(&::ULE::from_array([ - REPLACEMENT_CHARACTER as u16 - ])); - -pub(crate) const EMPTY_CHAR: &ZeroSlice = ZeroSlice::new_empty(); + zeroslice![u16; ::ULE::from_array; REPLACEMENT_CHARACTER as u16]; +pub(crate) const EMPTY_CHAR: &ZeroSlice = zeroslice![]; const SINGLE_REPLACEMENT_CHARACTER_CHAR: &ZeroSlice = - ZeroSlice::::from_ule_slice(&::ULE::from_array([REPLACEMENT_CHARACTER])); + zeroslice![char; ::ULE::from_array; REPLACEMENT_CHARACTER]; /// If `opt` is `Some`, unwrap it. If `None`, panic if debug assertions /// are enabled and return `default` if debug assertions are not enabled. diff --git a/components/collator/src/provider.rs b/components/collator/src/provider.rs index ad35fa4d5cd..1d9dd12ea59 100644 --- a/components/collator/src/provider.rs +++ b/components/collator/src/provider.rs @@ -22,8 +22,8 @@ use icu_collections::char16trie::Char16TrieIterator; use icu_collections::codepointtrie::CodePointTrie; use icu_provider::prelude::*; use zerovec::ule::AsULE; -use zerovec::ZeroSlice; use zerovec::ZeroVec; +use zerovec::{zeroslice, ZeroSlice}; use crate::elements::CollationElement; use crate::elements::CollationElement32; @@ -39,9 +39,8 @@ use super::CaseFirst; use super::MaxVariable; const SINGLE_U32: &ZeroSlice = - ZeroSlice::::from_ule_slice(&::ULE::from_array([FFFD_CE32_VALUE])); -const SINGLE_U64: &ZeroSlice = - ZeroSlice::::from_ule_slice(&::ULE::from_array([FFFD_CE_VALUE])); + zeroslice![u32; ::ULE::from_array; FFFD_CE32_VALUE]; +const SINGLE_U64: &ZeroSlice = zeroslice![u64; ::ULE::from_array; FFFD_CE_VALUE]; fn data_ce_to_primary(data_ce: u64, c: char) -> u32 { // Collation::getThreeBytePrimaryForOffsetData diff --git a/components/collections/src/codepointinvlist/cpinvlist.rs b/components/collections/src/codepointinvlist/cpinvlist.rs index 7ca713add82..907e0757acb 100644 --- a/components/collections/src/codepointinvlist/cpinvlist.rs +++ b/components/collections/src/codepointinvlist/cpinvlist.rs @@ -8,7 +8,7 @@ use alloc::vec::Vec; use core::{char, ops::RangeBounds, ops::RangeInclusive}; use yoke::Yokeable; use zerofrom::ZeroFrom; -use zerovec::{ule::AsULE, ZeroSlice, ZeroVec}; +use zerovec::{ule::AsULE, zeroslice, ZeroSlice, ZeroVec}; use super::CodePointInversionListError; use crate::codepointinvlist::utils::{deconstruct_range, is_valid_zv}; @@ -18,14 +18,11 @@ const BMP_MAX: u32 = 0xFFFF; /// Represents the inversion list for a set of all code points in the Basic Multilingual Plane. const BMP_INV_LIST_SLICE: &ZeroSlice = - ZeroSlice::::from_ule_slice(&::ULE::from_array([0x0, BMP_MAX + 1])); + zeroslice![u32; ::ULE::from_array; 0x0, BMP_MAX + 1]; /// Represents the inversion list for all of the code points in the Unicode range. const ALL_SLICE: &ZeroSlice = - ZeroSlice::::from_ule_slice(&::ULE::from_array([ - 0x0, - (char::MAX as u32) + 1, - ])); + zeroslice![u32; ::ULE::from_array; 0x0, (char::MAX as u32) + 1]; /// A membership wrapper for [`CodePointInversionList`]. /// diff --git a/components/collections/src/codepointtrie/benches/tries/gc_fast.rs b/components/collections/src/codepointtrie/benches/tries/gc_fast.rs index 3d81c241681..9df12cf9752 100644 --- a/components/collections/src/codepointtrie/benches/tries/gc_fast.rs +++ b/components/collections/src/codepointtrie/benches/tries/gc_fast.rs @@ -3,10 +3,11 @@ // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use icu_collections::codepointtrie::{CodePointTrieHeader, TrieType}; -use zerovec::{ule::RawBytesULE, ZeroSlice}; +use zerovec::ule::AsULE; +use zerovec::{zeroslice, ZeroSlice}; #[rustfmt::skip] -pub static INDEX: &ZeroSlice = ZeroSlice::::from_ule_slice(&RawBytesULE::<2>::from_array([ +pub static INDEX: &ZeroSlice = zeroslice![u16; ::ULE::from_array; 0,0x40,0x7f,0xbf,0xff,0x12e,0x16d,0x1ad,0x1e5,0x224,0x250,0x28e,0x2ce,0x2de,0x31e,0x34f, 0x38c,0x3bc,0x3fa,0x43a,0x44a,0x47b,0x4b2,0x4f2,0x532,0x572,0x5a3,0x5cf,0x60f,0x644,0x65e,0x69e, 0x6de,0x71e,0x756,0x78d,0x7ca,0x809,0x848,0x887,0x8c6,0x905,0x944,0x983,0x9c3,0xa01,0xa3f,0xa7f, @@ -198,7 +199,7 @@ pub static INDEX: &ZeroSlice = ZeroSlice::::from_ule_slice(&RawBytesUL 0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x380,0x380, 0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380, 0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0xaa0 -])); +]; #[rustfmt::skip] pub static DATA: &ZeroSlice = ZeroSlice::::from_ule_slice(&[ diff --git a/components/collections/src/codepointtrie/benches/tries/gc_small.rs b/components/collections/src/codepointtrie/benches/tries/gc_small.rs index 0e09435ec93..544a96afe96 100644 --- a/components/collections/src/codepointtrie/benches/tries/gc_small.rs +++ b/components/collections/src/codepointtrie/benches/tries/gc_small.rs @@ -3,10 +3,11 @@ // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use icu_collections::codepointtrie::{CodePointTrieHeader, TrieType}; -use zerovec::{ule::RawBytesULE, ZeroSlice}; +use zerovec::ule::AsULE; +use zerovec::{zeroslice, ZeroSlice}; #[rustfmt::skip] -pub static INDEX: &ZeroSlice = ZeroSlice::::from_ule_slice(&RawBytesULE::<2>::from_array([ +pub static INDEX: &ZeroSlice = zeroslice![u16; ::ULE::from_array; 0,0x40,0x7f,0xbf,0xff,0x12e,0x16d,0x1ad,0x1e5,0x224,0x250,0x28e,0x2ce,0x2de,0x31e,0x34f, 0x38c,0x3bc,0x3fa,0x43a,0x44a,0x47b,0x4b2,0x4f2,0x532,0x572,0x5a3,0x5cf,0x60f,0x644,0x65e,0x69e, 0x6de,0x71e,0x756,0x78d,0x7ca,0x809,0x848,0x887,0x8c6,0x905,0x944,0x983,0x9c3,0xa01,0xa3f,0xa7f, @@ -220,7 +221,7 @@ pub static INDEX: &ZeroSlice = ZeroSlice::::from_ule_slice(&RawBytesUL 0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0xb9d -])); +]; #[rustfmt::skip] pub static DATA: &ZeroSlice = ZeroSlice::::from_ule_slice(&[ diff --git a/components/normalizer/src/lib.rs b/components/normalizer/src/lib.rs index cc46b088b46..0eadd9bdc11 100644 --- a/components/normalizer/src/lib.rs +++ b/components/normalizer/src/lib.rs @@ -101,8 +101,7 @@ use utf16_iter::Utf16CharsEx; use utf8_iter::Utf8CharsEx; use write16::Write16; use zerofrom::ZeroFrom; -use zerovec::ule::AsULE; -use zerovec::ZeroSlice; +use zerovec::{zeroslice, ZeroSlice}; #[derive(Debug)] enum SupplementPayloadHolder { @@ -244,10 +243,9 @@ fn char_from_u16(u: u16) -> char { char_from_u32(u32::from(u)) } -const EMPTY_U16: &ZeroSlice = - ZeroSlice::::from_ule_slice(&::ULE::from_array([])); +const EMPTY_U16: &ZeroSlice = zeroslice![]; -const EMPTY_CHAR: &ZeroSlice = ZeroSlice::new_empty(); +const EMPTY_CHAR: &ZeroSlice = zeroslice![]; #[inline(always)] fn in_inclusive_range(c: char, start: char, end: char) -> bool { diff --git a/utils/zerovec/src/zerovec/slice.rs b/utils/zerovec/src/zerovec/slice.rs index 52ddc184b30..b6e4f78b44d 100644 --- a/utils/zerovec/src/zerovec/slice.rs +++ b/utils/zerovec/src/zerovec/slice.rs @@ -567,6 +567,7 @@ where #[cfg(test)] mod test { use super::*; + use crate::zeroslice; #[test] fn test_split_first() { @@ -576,21 +577,16 @@ mod test { } { // single element slice - const DATA: &ZeroSlice = - ZeroSlice::::from_ule_slice(&::ULE::from_array([211])); - assert_eq!((211, ZeroSlice::new_empty()), DATA.split_first().unwrap()); + const DATA: &ZeroSlice = zeroslice![u16; ::ULE::from_array; 211]; + assert_eq!((211, zeroslice![]), DATA.split_first().unwrap()); } { // slice with many elements. const DATA: &ZeroSlice = - ZeroSlice::::from_ule_slice(&::ULE::from_array([ - 211, 281, 421, 32973, - ])); + zeroslice![u16; ::ULE::from_array; 211, 281, 421, 32973]; const EXPECTED_VALUE: (u16, &ZeroSlice) = ( 211, - ZeroSlice::::from_ule_slice(&::ULE::from_array([ - 281, 421, 32973, - ])), + zeroslice![u16; ::ULE::from_array; 281, 421, 32973], ); assert_eq!(EXPECTED_VALUE, DATA.split_first().unwrap()); From 561fb6dbbaa1d4c6820e0071b3e71ac7fa9ce565 Mon Sep 17 00:00:00 2001 From: Niels Saurer Date: Thu, 25 May 2023 17:43:20 +0200 Subject: [PATCH 3/8] macro usage for ZeroSlice --- .../collections/src/codepointtrie/benches/tries/gc_fast.rs | 4 ++-- .../collections/src/codepointtrie/benches/tries/gc_small.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/collections/src/codepointtrie/benches/tries/gc_fast.rs b/components/collections/src/codepointtrie/benches/tries/gc_fast.rs index 9df12cf9752..bf499148ecf 100644 --- a/components/collections/src/codepointtrie/benches/tries/gc_fast.rs +++ b/components/collections/src/codepointtrie/benches/tries/gc_fast.rs @@ -202,7 +202,7 @@ pub static INDEX: &ZeroSlice = zeroslice![u16; ::ULE::from_ar ]; #[rustfmt::skip] -pub static DATA: &ZeroSlice = ZeroSlice::::from_ule_slice(&[ +pub static DATA: &ZeroSlice = zeroslice![u8; core::convert::identity; 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, 0xc,0x17,0x17,0x17,0x19,0x17,0x17,0x17,0x14,0x15,0x17,0x18,0x17,0x13,0x17,0x17, @@ -1112,7 +1112,7 @@ pub static DATA: &ZeroSlice = ZeroSlice::::from_ule_slice(&[ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x10,0x10, 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x11,0x11, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0,0 -]); +]; pub static HEADER: CodePointTrieHeader = CodePointTrieHeader { high_start: 0x110000, diff --git a/components/collections/src/codepointtrie/benches/tries/gc_small.rs b/components/collections/src/codepointtrie/benches/tries/gc_small.rs index 544a96afe96..904bdb42ee5 100644 --- a/components/collections/src/codepointtrie/benches/tries/gc_small.rs +++ b/components/collections/src/codepointtrie/benches/tries/gc_small.rs @@ -224,7 +224,7 @@ pub static INDEX: &ZeroSlice = zeroslice![u16; ::ULE::from_ar ]; #[rustfmt::skip] -pub static DATA: &ZeroSlice = ZeroSlice::::from_ule_slice(&[ +pub static DATA: &ZeroSlice = zeroslice![u8; core::convert::identity; 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, 0xc,0x17,0x17,0x17,0x19,0x17,0x17,0x17,0x14,0x15,0x17,0x18,0x17,0x13,0x17,0x17, @@ -849,7 +849,7 @@ pub static DATA: &ZeroSlice = ZeroSlice::::from_ule_slice(&[ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x10,0x10, 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x11,0x11, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0,0,0,0 -]); +]; pub static HEADER: CodePointTrieHeader = CodePointTrieHeader { high_start: 0x110000, From 79805017c46c83b00fb29d851861df3e1b346457 Mon Sep 17 00:00:00 2001 From: Niels Saurer Date: Thu, 1 Jun 2023 16:20:20 +0200 Subject: [PATCH 4/8] switch to zerovec! --- .../collections/src/codepointinvlist/cpinvlist.rs | 14 +++++++------- .../src/codepointtrie/benches/codepointtrie.rs | 8 ++++---- .../src/codepointtrie/benches/iai_cpt.rs | 8 ++++---- .../src/codepointtrie/benches/tries/gc_fast.rs | 6 +++--- .../src/codepointtrie/benches/tries/gc_small.rs | 6 +++--- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/components/collections/src/codepointinvlist/cpinvlist.rs b/components/collections/src/codepointinvlist/cpinvlist.rs index 0dd7435cca0..44b313b7f3b 100644 --- a/components/collections/src/codepointinvlist/cpinvlist.rs +++ b/components/collections/src/codepointinvlist/cpinvlist.rs @@ -8,7 +8,7 @@ use alloc::vec::Vec; use core::{char, ops::RangeBounds, ops::RangeInclusive}; use yoke::Yokeable; use zerofrom::ZeroFrom; -use zerovec::{ule::AsULE, zeroslice, ZeroSlice, ZeroVec}; +use zerovec::{ule::AsULE, zerovec, ZeroVec}; use super::CodePointInversionListError; use crate::codepointinvlist::utils::{deconstruct_range, is_valid_zv}; @@ -17,12 +17,12 @@ use crate::codepointinvlist::utils::{deconstruct_range, is_valid_zv}; const BMP_MAX: u32 = 0xFFFF; /// Represents the inversion list for a set of all code points in the Basic Multilingual Plane. -const BMP_INV_LIST_SLICE: &ZeroSlice = - zeroslice![u32; ::ULE::from_array; 0x0, BMP_MAX + 1]; +const BMP_INV_LIST_VEC: ZeroVec = + zerovec![u32; ::ULE::from_array; 0x0, BMP_MAX + 1]; /// Represents the inversion list for all of the code points in the Unicode range. -const ALL_SLICE: &ZeroSlice = - zeroslice![u32; ::ULE::from_array; 0x0, (char::MAX as u32) + 1]; +const ALL_VEC: ZeroVec = + zerovec![u32; ::ULE::from_array; 0x0, (char::MAX as u32) + 1]; /// A membership wrapper for [`CodePointInversionList`]. /// @@ -294,7 +294,7 @@ impl<'data> CodePointInversionList<'data> { /// ``` pub fn all() -> Self { Self { - inv_list: ALL_SLICE.as_zerovec(), + inv_list: ALL_VEC, size: (char::MAX as usize) + 1, } } @@ -323,7 +323,7 @@ impl<'data> CodePointInversionList<'data> { /// ``` pub fn bmp() -> Self { Self { - inv_list: BMP_INV_LIST_SLICE.as_zerovec(), + inv_list: BMP_INV_LIST_VEC, size: (BMP_MAX as usize) + 1, } } diff --git a/components/collections/src/codepointtrie/benches/codepointtrie.rs b/components/collections/src/codepointtrie/benches/codepointtrie.rs index 6cf38a704dd..5117330752a 100644 --- a/components/collections/src/codepointtrie/benches/codepointtrie.rs +++ b/components/collections/src/codepointtrie/benches/codepointtrie.rs @@ -33,8 +33,8 @@ fn one_hundred_code_points(sample_str: &str) -> String { fn get_trie_small() -> CodePointTrie<'static, u8> { CodePointTrie::try_new( tries::gc_small::HEADER, - tries::gc_small::INDEX.as_zerovec(), - tries::gc_small::DATA.as_zerovec(), + tries::gc_small::INDEX, + tries::gc_small::DATA, ) .unwrap() } @@ -43,8 +43,8 @@ fn get_trie_small() -> CodePointTrie<'static, u8> { fn get_trie_fast() -> CodePointTrie<'static, u8> { CodePointTrie::try_new( tries::gc_fast::HEADER, - tries::gc_fast::INDEX.as_zerovec(), - tries::gc_fast::DATA.as_zerovec(), + tries::gc_fast::INDEX, + tries::gc_fast::DATA, ) .unwrap() } diff --git a/components/collections/src/codepointtrie/benches/iai_cpt.rs b/components/collections/src/codepointtrie/benches/iai_cpt.rs index 63818019a03..3d57cbb4a16 100644 --- a/components/collections/src/codepointtrie/benches/iai_cpt.rs +++ b/components/collections/src/codepointtrie/benches/iai_cpt.rs @@ -14,8 +14,8 @@ const SAMPLE_STRING_MIXED: &str = "Dèclaråcion ЗАГАЛЬНА 世界人权 fn get_trie_small() -> CodePointTrie<'static, u8> { CodePointTrie::try_new( tries::gc_small::HEADER, - tries::gc_small::INDEX.as_zerovec(), - tries::gc_small::DATA.as_zerovec(), + tries::gc_small::INDEX, + tries::gc_small::DATA, ) .unwrap() } @@ -23,8 +23,8 @@ fn get_trie_small() -> CodePointTrie<'static, u8> { fn get_trie_fast() -> CodePointTrie<'static, u8> { CodePointTrie::try_new( tries::gc_fast::HEADER, - tries::gc_fast::INDEX.as_zerovec(), - tries::gc_fast::DATA.as_zerovec(), + tries::gc_fast::INDEX, + tries::gc_fast::DATA, ) .unwrap() } diff --git a/components/collections/src/codepointtrie/benches/tries/gc_fast.rs b/components/collections/src/codepointtrie/benches/tries/gc_fast.rs index bf499148ecf..f18d551081c 100644 --- a/components/collections/src/codepointtrie/benches/tries/gc_fast.rs +++ b/components/collections/src/codepointtrie/benches/tries/gc_fast.rs @@ -4,10 +4,10 @@ use icu_collections::codepointtrie::{CodePointTrieHeader, TrieType}; use zerovec::ule::AsULE; -use zerovec::{zeroslice, ZeroSlice}; +use zerovec::{zerovec, ZeroVec}; #[rustfmt::skip] -pub static INDEX: &ZeroSlice = zeroslice![u16; ::ULE::from_array; +pub const INDEX: ZeroVec = zerovec![u16; ::ULE::from_array; 0,0x40,0x7f,0xbf,0xff,0x12e,0x16d,0x1ad,0x1e5,0x224,0x250,0x28e,0x2ce,0x2de,0x31e,0x34f, 0x38c,0x3bc,0x3fa,0x43a,0x44a,0x47b,0x4b2,0x4f2,0x532,0x572,0x5a3,0x5cf,0x60f,0x644,0x65e,0x69e, 0x6de,0x71e,0x756,0x78d,0x7ca,0x809,0x848,0x887,0x8c6,0x905,0x944,0x983,0x9c3,0xa01,0xa3f,0xa7f, @@ -202,7 +202,7 @@ pub static INDEX: &ZeroSlice = zeroslice![u16; ::ULE::from_ar ]; #[rustfmt::skip] -pub static DATA: &ZeroSlice = zeroslice![u8; core::convert::identity; +pub const DATA: ZeroVec = zerovec![u8; core::convert::identity; 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, 0xc,0x17,0x17,0x17,0x19,0x17,0x17,0x17,0x14,0x15,0x17,0x18,0x17,0x13,0x17,0x17, diff --git a/components/collections/src/codepointtrie/benches/tries/gc_small.rs b/components/collections/src/codepointtrie/benches/tries/gc_small.rs index 904bdb42ee5..14705e3060c 100644 --- a/components/collections/src/codepointtrie/benches/tries/gc_small.rs +++ b/components/collections/src/codepointtrie/benches/tries/gc_small.rs @@ -4,10 +4,10 @@ use icu_collections::codepointtrie::{CodePointTrieHeader, TrieType}; use zerovec::ule::AsULE; -use zerovec::{zeroslice, ZeroSlice}; +use zerovec::{zerovec, ZeroVec}; #[rustfmt::skip] -pub static INDEX: &ZeroSlice = zeroslice![u16; ::ULE::from_array; +pub const INDEX: ZeroVec = zerovec![u16; ::ULE::from_array; 0,0x40,0x7f,0xbf,0xff,0x12e,0x16d,0x1ad,0x1e5,0x224,0x250,0x28e,0x2ce,0x2de,0x31e,0x34f, 0x38c,0x3bc,0x3fa,0x43a,0x44a,0x47b,0x4b2,0x4f2,0x532,0x572,0x5a3,0x5cf,0x60f,0x644,0x65e,0x69e, 0x6de,0x71e,0x756,0x78d,0x7ca,0x809,0x848,0x887,0x8c6,0x905,0x944,0x983,0x9c3,0xa01,0xa3f,0xa7f, @@ -224,7 +224,7 @@ pub static INDEX: &ZeroSlice = zeroslice![u16; ::ULE::from_ar ]; #[rustfmt::skip] -pub static DATA: &ZeroSlice = zeroslice![u8; core::convert::identity; +pub const DATA: ZeroVec = zerovec![u8; core::convert::identity; 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, 0xc,0x17,0x17,0x17,0x19,0x17,0x17,0x17,0x14,0x15,0x17,0x18,0x17,0x13,0x17,0x17, From 97b717edb4d43926ff2d243adb9c0fb747254ee6 Mon Sep 17 00:00:00 2001 From: Niels Saurer Date: Thu, 1 Jun 2023 17:25:17 +0200 Subject: [PATCH 5/8] zeroslice macros using macro repetition instead of array fn --- components/collator/src/elements.rs | 4 +- components/collator/src/provider.rs | 5 ++- .../src/codepointinvlist/cpinvlist.rs | 4 +- .../codepointtrie/benches/tries/gc_fast.rs | 2 +- .../codepointtrie/benches/tries/gc_small.rs | 2 +- utils/zerovec/src/ule/plain.rs | 36 +++++++++++---- utils/zerovec/src/ule/unvalidated.rs | 9 ++++ utils/zerovec/src/zerovec/mod.rs | 45 +++++++++---------- utils/zerovec/src/zerovec/slice.rs | 6 +-- 9 files changed, 70 insertions(+), 43 deletions(-) diff --git a/components/collator/src/elements.rs b/components/collator/src/elements.rs index 7e32578a2c6..811877ad2f6 100644 --- a/components/collator/src/elements.rs +++ b/components/collator/src/elements.rs @@ -149,11 +149,11 @@ pub(crate) const FFFD_CE32: CollationElement32 = CollationElement32(FFFD_CE32_VA pub(crate) const EMPTY_U16: &ZeroSlice = zeroslice![]; const SINGLE_REPLACEMENT_CHARACTER_U16: &ZeroSlice = - zeroslice![u16; ::ULE::from_array; REPLACEMENT_CHARACTER as u16]; + zeroslice![u16; ::ULE::from_unsigned; REPLACEMENT_CHARACTER as u16]; pub(crate) const EMPTY_CHAR: &ZeroSlice = zeroslice![]; const SINGLE_REPLACEMENT_CHARACTER_CHAR: &ZeroSlice = - zeroslice![char; ::ULE::from_array; REPLACEMENT_CHARACTER]; + zeroslice![char; ::ULE::from_aligned; REPLACEMENT_CHARACTER]; /// If `opt` is `Some`, unwrap it. If `None`, panic if debug assertions /// are enabled and return `default` if debug assertions are not enabled. diff --git a/components/collator/src/provider.rs b/components/collator/src/provider.rs index 1d9dd12ea59..d7c83d8f307 100644 --- a/components/collator/src/provider.rs +++ b/components/collator/src/provider.rs @@ -39,8 +39,9 @@ use super::CaseFirst; use super::MaxVariable; const SINGLE_U32: &ZeroSlice = - zeroslice![u32; ::ULE::from_array; FFFD_CE32_VALUE]; -const SINGLE_U64: &ZeroSlice = zeroslice![u64; ::ULE::from_array; FFFD_CE_VALUE]; + zeroslice![u32; ::ULE::from_unsigned; FFFD_CE32_VALUE]; +const SINGLE_U64: &ZeroSlice = + zeroslice![u64; ::ULE::from_unsigned; FFFD_CE_VALUE]; fn data_ce_to_primary(data_ce: u64, c: char) -> u32 { // Collation::getThreeBytePrimaryForOffsetData diff --git a/components/collections/src/codepointinvlist/cpinvlist.rs b/components/collections/src/codepointinvlist/cpinvlist.rs index 44b313b7f3b..6d95416ea21 100644 --- a/components/collections/src/codepointinvlist/cpinvlist.rs +++ b/components/collections/src/codepointinvlist/cpinvlist.rs @@ -18,11 +18,11 @@ const BMP_MAX: u32 = 0xFFFF; /// Represents the inversion list for a set of all code points in the Basic Multilingual Plane. const BMP_INV_LIST_VEC: ZeroVec = - zerovec![u32; ::ULE::from_array; 0x0, BMP_MAX + 1]; + zerovec![u32; ::ULE::from_unsigned; 0x0, BMP_MAX + 1]; /// Represents the inversion list for all of the code points in the Unicode range. const ALL_VEC: ZeroVec = - zerovec![u32; ::ULE::from_array; 0x0, (char::MAX as u32) + 1]; + zerovec![u32; ::ULE::from_unsigned; 0x0, (char::MAX as u32) + 1]; /// A membership wrapper for [`CodePointInversionList`]. /// diff --git a/components/collections/src/codepointtrie/benches/tries/gc_fast.rs b/components/collections/src/codepointtrie/benches/tries/gc_fast.rs index f18d551081c..ba25814cb31 100644 --- a/components/collections/src/codepointtrie/benches/tries/gc_fast.rs +++ b/components/collections/src/codepointtrie/benches/tries/gc_fast.rs @@ -7,7 +7,7 @@ use zerovec::ule::AsULE; use zerovec::{zerovec, ZeroVec}; #[rustfmt::skip] -pub const INDEX: ZeroVec = zerovec![u16; ::ULE::from_array; +pub const INDEX: ZeroVec = zerovec![u16; ::ULE::from_unsigned; 0,0x40,0x7f,0xbf,0xff,0x12e,0x16d,0x1ad,0x1e5,0x224,0x250,0x28e,0x2ce,0x2de,0x31e,0x34f, 0x38c,0x3bc,0x3fa,0x43a,0x44a,0x47b,0x4b2,0x4f2,0x532,0x572,0x5a3,0x5cf,0x60f,0x644,0x65e,0x69e, 0x6de,0x71e,0x756,0x78d,0x7ca,0x809,0x848,0x887,0x8c6,0x905,0x944,0x983,0x9c3,0xa01,0xa3f,0xa7f, diff --git a/components/collections/src/codepointtrie/benches/tries/gc_small.rs b/components/collections/src/codepointtrie/benches/tries/gc_small.rs index 14705e3060c..26b30d444b1 100644 --- a/components/collections/src/codepointtrie/benches/tries/gc_small.rs +++ b/components/collections/src/codepointtrie/benches/tries/gc_small.rs @@ -7,7 +7,7 @@ use zerovec::ule::AsULE; use zerovec::{zerovec, ZeroVec}; #[rustfmt::skip] -pub const INDEX: ZeroVec = zerovec![u16; ::ULE::from_array; +pub const INDEX: ZeroVec = zerovec![u16; ::ULE::from_unsigned; 0,0x40,0x7f,0xbf,0xff,0x12e,0x16d,0x1ad,0x1e5,0x224,0x250,0x28e,0x2ce,0x2de,0x31e,0x34f, 0x38c,0x3bc,0x3fa,0x43a,0x44a,0x47b,0x4b2,0x4f2,0x532,0x572,0x5a3,0x5cf,0x60f,0x644,0x65e,0x69e, 0x6de,0x71e,0x756,0x78d,0x7ca,0x809,0x848,0x887,0x8c6,0x905,0x944,0x983,0x9c3,0xa01,0xa3f,0xa7f, diff --git a/utils/zerovec/src/ule/plain.rs b/utils/zerovec/src/ule/plain.rs index dc8e4510e0a..f244f6b6825 100644 --- a/utils/zerovec/src/ule/plain.rs +++ b/utils/zerovec/src/ule/plain.rs @@ -111,7 +111,7 @@ macro_rules! impl_const_constructors { } macro_rules! impl_byte_slice_type { - ($type:ty, $size:literal) => { + ($single_fn:ident, $type:ty, $size:literal) => { impl From<$type> for RawBytesULE<$size> { #[inline] fn from(value: $type) -> Self { @@ -132,6 +132,24 @@ macro_rules! impl_byte_slice_type { // EqULE is true because $type and RawBytesULE<$size> // have the same byte sequence on little-endian unsafe impl EqULE for $type {} + + impl RawBytesULE<$size> { + pub const fn $single_fn(v: $type) -> Self { + RawBytesULE(v.to_le_bytes()) + } + } + }; +} + +macro_rules! impl_byte_slice_unsigned_type { + ($type:ty, $size:literal) => { + impl_byte_slice_type!(from_unsigned, $type, $size); + }; +} + +macro_rules! impl_byte_slice_signed_type { + ($type:ty, $size:literal) => { + impl_byte_slice_type!(from_signed, $type, $size); }; } @@ -140,15 +158,15 @@ impl_byte_slice_size!(u32, 4); impl_byte_slice_size!(u64, 8); impl_byte_slice_size!(u128, 16); -impl_byte_slice_type!(u16, 2); -impl_byte_slice_type!(u32, 4); -impl_byte_slice_type!(u64, 8); -impl_byte_slice_type!(u128, 16); +impl_byte_slice_unsigned_type!(u16, 2); +impl_byte_slice_unsigned_type!(u32, 4); +impl_byte_slice_unsigned_type!(u64, 8); +impl_byte_slice_unsigned_type!(u128, 16); -impl_byte_slice_type!(i16, 2); -impl_byte_slice_type!(i32, 4); -impl_byte_slice_type!(i64, 8); -impl_byte_slice_type!(i128, 16); +impl_byte_slice_signed_type!(i16, 2); +impl_byte_slice_signed_type!(i32, 4); +impl_byte_slice_signed_type!(i64, 8); +impl_byte_slice_signed_type!(i128, 16); impl_const_constructors!(u8, 1); impl_const_constructors!(u16, 2); diff --git a/utils/zerovec/src/ule/unvalidated.rs b/utils/zerovec/src/ule/unvalidated.rs index 33a8656a7df..21cfb0c0d58 100644 --- a/utils/zerovec/src/ule/unvalidated.rs +++ b/utils/zerovec/src/ule/unvalidated.rs @@ -322,6 +322,15 @@ impl UnvalidatedChar { } } +impl RawBytesULE<3> { + /// Converts a [`UnvalidatedChar`] to its ULE type. This is equivalent to calling + /// [`AsULE::to_unaligned`]. + #[inline] + pub const fn from_unvalidated_char(uc: UnvalidatedChar) -> Self { + RawBytesULE(uc.0) + } +} + impl AsULE for UnvalidatedChar { type ULE = RawBytesULE<3>; diff --git a/utils/zerovec/src/zerovec/mod.rs b/utils/zerovec/src/zerovec/mod.rs index 9f1c439cd4f..943f230647e 100644 --- a/utils/zerovec/src/zerovec/mod.rs +++ b/utils/zerovec/src/zerovec/mod.rs @@ -924,9 +924,8 @@ impl FromIterator for ZeroVec<'_, T> { /// # Arguments /// /// * `$aligned` - The type of an element in its canonical, aligned form, e.g., `char`. -/// * `$array_fn` - A const function that converts an array of `$aligned` elements into an array -/// of their unaligned equivalents, e.g., -/// `const fn from_array(arr: [char; N]) -> [::ULE; N]`. +/// * `$convert` - A const function that converts an `$aligned` into its unaligned equivalent, e.g., +/// `const fn from_aligned(a: CanonicalType) -> CanonicalType::ULE`. /// * `$x` - The elements that the `ZeroSlice` will hold. /// /// # Examples @@ -935,42 +934,42 @@ impl FromIterator for ZeroVec<'_, T> { /// /// ``` /// use zerovec::{ZeroSlice, zeroslice, ule::AsULE}; +/// use zerovec::ule::UnvalidatedChar; /// -/// const SIGNATURE: &ZeroSlice = zeroslice![char; ::ULE::from_array; 'b', 'y', 'e', '✌']; +/// const SIGNATURE: &ZeroSlice = zeroslice![char; ::ULE::from_aligned; 'b', 'y', 'e', '✌']; /// const EMPTY: &ZeroSlice = zeroslice![]; +/// const UC: &ZeroSlice = +/// zeroslice![ +/// UnvalidatedChar; +/// ::ULE::from_unvalidated_char; +/// UnvalidatedChar::from_char('a'), +/// ]; /// let empty: &ZeroSlice = zeroslice![]; -/// let nums = zeroslice![u32; ::ULE::from_array; 1, 2, 3, 4, 5]; +/// let nums = zeroslice![u32; ::ULE::from_unsigned; 1, 2, 3, 4, 5]; /// assert_eq!(nums.last().unwrap(), 5); /// ``` /// /// Using a custom array-conversion function: /// /// ``` -/// use zerovec::{ZeroSlice, zeroslice}; +/// use zerovec::{ZeroSlice, zeroslice, ule::AsULE, ule::RawBytesULE}; /// -/// mod conversion { -/// use zerovec::ule::RawBytesULE; -/// pub(super) const fn i16_array_to_be_array(arr: [i16; N]) -> [RawBytesULE<2>; N] { -/// let mut result = [RawBytesULE([0; 2]); N]; -/// let mut i = 0; -/// while i < N { -/// result[i] = RawBytesULE(arr[i].to_be_bytes()); -/// i += 1; -/// } -/// result -/// } +/// const fn be_convert(num: i16) -> ::ULE { +/// RawBytesULE(num.to_be_bytes()) /// } /// -/// const NUMBERS: &ZeroSlice = zeroslice![i16; conversion::i16_array_to_be_array; 1, -2, 3, -4, 5]; +/// const NUMBERS_BE: &ZeroSlice = zeroslice![i16; be_convert; 1, -2, 3, -4, 5]; /// ``` #[macro_export] macro_rules! zeroslice { () => ( $crate::ZeroSlice::new_empty() ); - ($aligned:ty; $array_fn:expr; $($x:expr),+ $(,)?) => ( + ($aligned:ty; $convert:expr; $($x:expr),+ $(,)?) => ( $crate::ZeroSlice::<$aligned>::from_ule_slice( - {const X: &[<$aligned as $crate::ule::AsULE>::ULE] = &$array_fn([$($x),+]); X} + {const X: &[<$aligned as $crate::ule::AsULE>::ULE] = &[ + $($convert($x)),* + ]; X} ) ); } @@ -984,7 +983,7 @@ macro_rules! zeroslice { /// ``` /// use zerovec::{ZeroVec, zerovec, ule::AsULE}; /// -/// const SIGNATURE: ZeroVec = zerovec![char; ::ULE::from_array; 'a', 'y', 'e', '✌']; +/// const SIGNATURE: ZeroVec = zerovec![char; ::ULE::from_aligned; 'a', 'y', 'e', '✌']; /// assert!(!SIGNATURE.is_owned()); /// /// const EMPTY: ZeroVec = zerovec![]; @@ -995,8 +994,8 @@ macro_rules! zerovec { () => ( $crate::ZeroVec::new() ); - ($aligned:ty; $array_fn:expr; $($x:expr),+ $(,)?) => ( - $crate::zeroslice![$aligned; $array_fn; $($x),+].as_zerovec() + ($aligned:ty; $convert:expr; $($x:expr),+ $(,)?) => ( + $crate::zeroslice![$aligned; $convert; $($x),+].as_zerovec() ); } diff --git a/utils/zerovec/src/zerovec/slice.rs b/utils/zerovec/src/zerovec/slice.rs index b6e4f78b44d..493dd3d56a5 100644 --- a/utils/zerovec/src/zerovec/slice.rs +++ b/utils/zerovec/src/zerovec/slice.rs @@ -577,16 +577,16 @@ mod test { } { // single element slice - const DATA: &ZeroSlice = zeroslice![u16; ::ULE::from_array; 211]; + const DATA: &ZeroSlice = zeroslice![u16; ::ULE::from_unsigned; 211]; assert_eq!((211, zeroslice![]), DATA.split_first().unwrap()); } { // slice with many elements. const DATA: &ZeroSlice = - zeroslice![u16; ::ULE::from_array; 211, 281, 421, 32973]; + zeroslice![u16; ::ULE::from_unsigned; 211, 281, 421, 32973]; const EXPECTED_VALUE: (u16, &ZeroSlice) = ( 211, - zeroslice![u16; ::ULE::from_array; 281, 421, 32973], + zeroslice![u16; ::ULE::from_unsigned; 281, 421, 32973], ); assert_eq!(EXPECTED_VALUE, DATA.split_first().unwrap()); From 2397ad1fff1f914125d02685b65806694db1cbb0 Mon Sep 17 00:00:00 2001 From: Niels Saurer Date: Thu, 1 Jun 2023 17:51:56 +0200 Subject: [PATCH 6/8] remove from_array functions --- utils/zerovec/src/ule/chars.rs | 65 +++++++++++------------------- utils/zerovec/src/ule/plain.rs | 13 ------ utils/zerovec/src/zerovec/slice.rs | 18 ++++----- 3 files changed, 31 insertions(+), 65 deletions(-) diff --git a/utils/zerovec/src/ule/chars.rs b/utils/zerovec/src/ule/chars.rs index cc6d49e0c57..699d3a0c66e 100644 --- a/utils/zerovec/src/ule/chars.rs +++ b/utils/zerovec/src/ule/chars.rs @@ -6,7 +6,6 @@ //! ULE implementation for the `char` type. use super::*; -use crate::impl_ule_from_array; use core::cmp::Ordering; use core::convert::TryFrom; @@ -51,8 +50,6 @@ impl CharULE { let [u0, u1, u2, _u3] = (c as u32).to_le_bytes(); Self([u0, u1, u2]) } - - impl_ule_from_array!(char, CharULE, Self([0; 3])); } // Safety (based on the safety checklist on the ULE trait): @@ -120,47 +117,31 @@ impl Ord for CharULE { mod test { use super::*; - #[test] - fn test_from_array() { - const CHARS: [char; 2] = ['a', '🙃']; - const CHARS_ULE: [CharULE; 2] = CharULE::from_array(CHARS); - assert_eq!( - CharULE::as_byte_slice(&CHARS_ULE), - &[0x61, 0x00, 0x00, 0x43, 0xF6, 0x01] - ); - } - - #[test] - fn test_from_array_zst() { - const CHARS: [char; 0] = []; - const CHARS_ULE: [CharULE; 0] = CharULE::from_array(CHARS); - let bytes = CharULE::as_byte_slice(&CHARS_ULE); - let empty: &[u8] = &[]; - assert_eq!(bytes, empty); - } - #[test] fn test_parse() { - // 1-byte, 2-byte, 3-byte, and two 4-byte character in UTF-8 (not as relevant in UTF-32) - let chars = ['w', 'ω', '文', '𑄃', '🙃']; - let char_ules: Vec = chars.iter().copied().map(char::to_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 = parsed_ules - .iter() - .copied() - .map(char::from_unaligned) - .collect(); - assert_eq!(&chars, parsed_chars.as_slice()); - - // Compare to golden expected data - assert_eq!( - &[119, 0, 0, 201, 3, 0, 135, 101, 0, 3, 17, 1, 67, 246, 1], - char_bytes - ); + let conversion_functions = [char::to_unaligned, CharULE::from_aligned]; + for f in &conversion_functions { + // 1-byte, 2-byte, 3-byte, and two 4-byte character in UTF-8 (not as relevant in UTF-32) + let chars = ['w', 'ω', '文', '𑄃', '🙃']; + let char_ules: Vec = chars.iter().copied().map(f).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 = parsed_ules + .iter() + .copied() + .map(char::from_unaligned) + .collect(); + assert_eq!(&chars, parsed_chars.as_slice()); + + // Compare to golden expected data + assert_eq!( + &[119, 0, 0, 201, 3, 0, 135, 101, 0, 3, 17, 1, 67, 246, 1], + char_bytes + ); + } } #[test] diff --git a/utils/zerovec/src/ule/plain.rs b/utils/zerovec/src/ule/plain.rs index f244f6b6825..87f2dd23ec8 100644 --- a/utils/zerovec/src/ule/plain.rs +++ b/utils/zerovec/src/ule/plain.rs @@ -6,7 +6,6 @@ //! ULE implementation for Plain Old Data types, including all sized integers. use super::*; -use crate::impl_ule_from_array; use crate::ZeroSlice; use core::num::{NonZeroI8, NonZeroU8}; @@ -67,18 +66,6 @@ macro_rules! impl_byte_slice_size { pub fn as_unsigned_int(&self) -> $unsigned { <$unsigned as $crate::ule::AsULE>::from_unaligned(*self) } - - #[doc = concat!("Converts a `", stringify!($unsigned), "` to a `RawBytesULE`. This is equivalent to calling [`AsULE::to_unaligned()`] on the appropriately sized type.")] - #[inline] - pub const fn from_aligned(value: $unsigned) -> Self { - Self(value.to_le_bytes()) - } - - impl_ule_from_array!( - $unsigned, - RawBytesULE<$size>, - RawBytesULE([0; $size]) - ); } }; } diff --git a/utils/zerovec/src/zerovec/slice.rs b/utils/zerovec/src/zerovec/slice.rs index 493dd3d56a5..8edf421c84a 100644 --- a/utils/zerovec/src/zerovec/slice.rs +++ b/utils/zerovec/src/zerovec/slice.rs @@ -22,12 +22,10 @@ use core::ops::Range; /// /// ``` /// use zerovec::ule::AsULE; -/// use zerovec::ZeroSlice; +/// use zerovec::{ZeroSlice, zeroslice}; /// /// const DATA: &ZeroSlice = -/// ZeroSlice::::from_ule_slice(&::ULE::from_array([ -/// 211, 281, 421, 32973, -/// ])); +/// zeroslice![u16; ::ULE::from_unsigned; 211, 281, 421, 32973]; /// /// assert_eq!(DATA.get(1), Some(281)); /// ``` @@ -372,17 +370,17 @@ where /// /// ``` /// use zerovec::ule::AsULE; - /// use zerovec::ZeroSlice; + /// use zerovec::{ZeroSlice, zeroslice}; /// /// const DATA: &ZeroSlice = - /// ZeroSlice::::from_ule_slice(&::ULE::from_array([ - /// 211, 281, 421, 32973, - /// ])); + /// zeroslice![u16; ::ULE::from_unsigned; + /// 211, 281, 421, 32973 + /// ]; /// const EXPECTED_VALUE: (u16, &ZeroSlice) = ( /// 211, - /// ZeroSlice::::from_ule_slice(&::ULE::from_array([ + /// zeroslice![u16; ::ULE::from_unsigned; /// 281, 421, 32973, - /// ])), + /// ], /// ); /// assert_eq!(EXPECTED_VALUE, DATA.split_first().unwrap()); /// ``` From 66a1a35561a47240825c1d5dd03c750beae52296 Mon Sep 17 00:00:00 2001 From: Niels Saurer Date: Thu, 1 Jun 2023 18:06:06 +0200 Subject: [PATCH 7/8] Revert "remove from_array functions" This reverts commit 2397ad1fff1f914125d02685b65806694db1cbb0. --- utils/zerovec/src/ule/chars.rs | 65 +++++++++++++++++++----------- utils/zerovec/src/ule/plain.rs | 13 ++++++ utils/zerovec/src/zerovec/slice.rs | 18 +++++---- 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/utils/zerovec/src/ule/chars.rs b/utils/zerovec/src/ule/chars.rs index 699d3a0c66e..cc6d49e0c57 100644 --- a/utils/zerovec/src/ule/chars.rs +++ b/utils/zerovec/src/ule/chars.rs @@ -6,6 +6,7 @@ //! ULE implementation for the `char` type. use super::*; +use crate::impl_ule_from_array; use core::cmp::Ordering; use core::convert::TryFrom; @@ -50,6 +51,8 @@ impl CharULE { let [u0, u1, u2, _u3] = (c as u32).to_le_bytes(); Self([u0, u1, u2]) } + + impl_ule_from_array!(char, CharULE, Self([0; 3])); } // Safety (based on the safety checklist on the ULE trait): @@ -117,31 +120,47 @@ impl Ord for CharULE { mod test { use super::*; + #[test] + fn test_from_array() { + const CHARS: [char; 2] = ['a', '🙃']; + const CHARS_ULE: [CharULE; 2] = CharULE::from_array(CHARS); + assert_eq!( + CharULE::as_byte_slice(&CHARS_ULE), + &[0x61, 0x00, 0x00, 0x43, 0xF6, 0x01] + ); + } + + #[test] + fn test_from_array_zst() { + const CHARS: [char; 0] = []; + const CHARS_ULE: [CharULE; 0] = CharULE::from_array(CHARS); + let bytes = CharULE::as_byte_slice(&CHARS_ULE); + let empty: &[u8] = &[]; + assert_eq!(bytes, empty); + } + #[test] fn test_parse() { - let conversion_functions = [char::to_unaligned, CharULE::from_aligned]; - for f in &conversion_functions { - // 1-byte, 2-byte, 3-byte, and two 4-byte character in UTF-8 (not as relevant in UTF-32) - let chars = ['w', 'ω', '文', '𑄃', '🙃']; - let char_ules: Vec = chars.iter().copied().map(f).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 = parsed_ules - .iter() - .copied() - .map(char::from_unaligned) - .collect(); - assert_eq!(&chars, parsed_chars.as_slice()); - - // Compare to golden expected data - assert_eq!( - &[119, 0, 0, 201, 3, 0, 135, 101, 0, 3, 17, 1, 67, 246, 1], - char_bytes - ); - } + // 1-byte, 2-byte, 3-byte, and two 4-byte character in UTF-8 (not as relevant in UTF-32) + let chars = ['w', 'ω', '文', '𑄃', '🙃']; + let char_ules: Vec = chars.iter().copied().map(char::to_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 = parsed_ules + .iter() + .copied() + .map(char::from_unaligned) + .collect(); + assert_eq!(&chars, parsed_chars.as_slice()); + + // Compare to golden expected data + assert_eq!( + &[119, 0, 0, 201, 3, 0, 135, 101, 0, 3, 17, 1, 67, 246, 1], + char_bytes + ); } #[test] diff --git a/utils/zerovec/src/ule/plain.rs b/utils/zerovec/src/ule/plain.rs index 87f2dd23ec8..f244f6b6825 100644 --- a/utils/zerovec/src/ule/plain.rs +++ b/utils/zerovec/src/ule/plain.rs @@ -6,6 +6,7 @@ //! ULE implementation for Plain Old Data types, including all sized integers. use super::*; +use crate::impl_ule_from_array; use crate::ZeroSlice; use core::num::{NonZeroI8, NonZeroU8}; @@ -66,6 +67,18 @@ macro_rules! impl_byte_slice_size { pub fn as_unsigned_int(&self) -> $unsigned { <$unsigned as $crate::ule::AsULE>::from_unaligned(*self) } + + #[doc = concat!("Converts a `", stringify!($unsigned), "` to a `RawBytesULE`. This is equivalent to calling [`AsULE::to_unaligned()`] on the appropriately sized type.")] + #[inline] + pub const fn from_aligned(value: $unsigned) -> Self { + Self(value.to_le_bytes()) + } + + impl_ule_from_array!( + $unsigned, + RawBytesULE<$size>, + RawBytesULE([0; $size]) + ); } }; } diff --git a/utils/zerovec/src/zerovec/slice.rs b/utils/zerovec/src/zerovec/slice.rs index 8edf421c84a..493dd3d56a5 100644 --- a/utils/zerovec/src/zerovec/slice.rs +++ b/utils/zerovec/src/zerovec/slice.rs @@ -22,10 +22,12 @@ use core::ops::Range; /// /// ``` /// use zerovec::ule::AsULE; -/// use zerovec::{ZeroSlice, zeroslice}; +/// use zerovec::ZeroSlice; /// /// const DATA: &ZeroSlice = -/// zeroslice![u16; ::ULE::from_unsigned; 211, 281, 421, 32973]; +/// ZeroSlice::::from_ule_slice(&::ULE::from_array([ +/// 211, 281, 421, 32973, +/// ])); /// /// assert_eq!(DATA.get(1), Some(281)); /// ``` @@ -370,17 +372,17 @@ where /// /// ``` /// use zerovec::ule::AsULE; - /// use zerovec::{ZeroSlice, zeroslice}; + /// use zerovec::ZeroSlice; /// /// const DATA: &ZeroSlice = - /// zeroslice![u16; ::ULE::from_unsigned; - /// 211, 281, 421, 32973 - /// ]; + /// ZeroSlice::::from_ule_slice(&::ULE::from_array([ + /// 211, 281, 421, 32973, + /// ])); /// const EXPECTED_VALUE: (u16, &ZeroSlice) = ( /// 211, - /// zeroslice![u16; ::ULE::from_unsigned; + /// ZeroSlice::::from_ule_slice(&::ULE::from_array([ /// 281, 421, 32973, - /// ], + /// ])), /// ); /// assert_eq!(EXPECTED_VALUE, DATA.split_first().unwrap()); /// ``` From 67de36e17ef837cd227020bd7f44000e820421a5 Mon Sep 17 00:00:00 2001 From: Niels Saurer Date: Thu, 1 Jun 2023 18:10:37 +0200 Subject: [PATCH 8/8] clarify macros only working in const --- utils/zerovec/src/zerovec/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/utils/zerovec/src/zerovec/mod.rs b/utils/zerovec/src/zerovec/mod.rs index 943f230647e..a36b53289dd 100644 --- a/utils/zerovec/src/zerovec/mod.rs +++ b/utils/zerovec/src/zerovec/mod.rs @@ -919,7 +919,8 @@ impl FromIterator for ZeroVec<'_, T> { } } -/// Convenience wrapper for [`ZeroSlice::from_ule_slice`]. The value will be created at compile-time. +/// Convenience wrapper for [`ZeroSlice::from_ule_slice`]. The value will be created at compile-time, +/// meaning that all arguments must also be constant. /// /// # Arguments /// @@ -974,7 +975,8 @@ macro_rules! zeroslice { ); } -/// Creates a borrowed `ZeroVec`. Convenience wrapper for `zeroslice![...].as_zerovec()`. +/// Creates a borrowed `ZeroVec`. Convenience wrapper for `zeroslice![...].as_zerovec()`. The value +/// will be created at compile-time, meaning that all arguments must also be constant. /// /// See [`zeroslice!`](crate::zeroslice) for more information. ///