diff options
Diffstat (limited to 'vendor/tinystr/src')
-rw-r--r-- | vendor/tinystr/src/ascii.rs | 12 | ||||
-rw-r--r-- | vendor/tinystr/src/databake.rs | 29 | ||||
-rw-r--r-- | vendor/tinystr/src/lib.rs | 2 | ||||
-rw-r--r-- | vendor/tinystr/src/serde.rs | 2 | ||||
-rw-r--r-- | vendor/tinystr/src/ule.rs | 48 | ||||
-rw-r--r-- | vendor/tinystr/src/unvalidated.rs | 104 |
6 files changed, 186 insertions, 11 deletions
diff --git a/vendor/tinystr/src/ascii.rs b/vendor/tinystr/src/ascii.rs index f39f39b73..9ab694f02 100644 --- a/vendor/tinystr/src/ascii.rs +++ b/vendor/tinystr/src/ascii.rs @@ -140,21 +140,23 @@ impl<const N: usize> TinyAsciiStr<N> { pub const fn as_bytes(&self) -> &[u8] { // Safe because `self.bytes.as_slice()` pointer-casts to `&[u8]`, // and changing the length of that slice to self.len() < N is safe. - unsafe { core::mem::transmute((self.bytes.as_slice().as_ptr(), self.len())) } + unsafe { + core::slice::from_raw_parts(self.bytes.as_slice().as_ptr() as *const u8, self.len()) + } } #[inline] #[must_use] pub const fn all_bytes(&self) -> &[u8; N] { // SAFETY: `self.bytes` has same size as [u8; N] - unsafe { core::mem::transmute(&self.bytes) } + unsafe { &*(self.bytes.as_ptr() as *const [u8; N]) } } #[inline] #[must_use] - /// Resizes a TinyAsciiStr<N> to a TinyAsciiStr<M>. + /// Resizes a `TinyAsciiStr<N>` to a `TinyAsciiStr<M>`. /// - /// If M < len() the string gets truncated, otherwise only the + /// If `M < len()` the string gets truncated, otherwise only the /// memory representation changes. pub const fn resize<const M: usize>(self) -> TinyAsciiStr<M> { let mut bytes = [0; M]; @@ -729,7 +731,7 @@ mod test { }; let expected = reference_f(&s); let actual = tinystr_f(t); - assert_eq!(expected, actual, "TinyAsciiStr<{}>: {:?}", N, s); + assert_eq!(expected, actual, "TinyAsciiStr<{N}>: {s:?}"); } } diff --git a/vendor/tinystr/src/databake.rs b/vendor/tinystr/src/databake.rs index e10c194f8..0b127f97c 100644 --- a/vendor/tinystr/src/databake.rs +++ b/vendor/tinystr/src/databake.rs @@ -3,6 +3,7 @@ // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use crate::TinyAsciiStr; +use crate::UnvalidatedTinyAsciiStr; use databake::*; impl<const N: usize> Bake for TinyAsciiStr<N> { @@ -10,7 +11,27 @@ impl<const N: usize> Bake for TinyAsciiStr<N> { env.insert("tinystr"); let string = self.as_str(); quote! { - ::tinystr::tinystr!(#N, #string) + tinystr::tinystr!(#N, #string) + } + } +} + +impl<const N: usize> databake::Bake for UnvalidatedTinyAsciiStr<N> { + fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream { + match self.try_into_tinystr() { + Ok(tiny) => { + let tiny = tiny.bake(env); + databake::quote! { + #tiny.to_unvalidated() + } + } + Err(_) => { + let bytes = self.0.bake(env); + env.insert("tinystr"); + databake::quote! { + tinystr::UnvalidatedTinyAsciiStr::from_bytes_unchecked(*#bytes) + } + } } } } @@ -19,3 +40,9 @@ impl<const N: usize> Bake for TinyAsciiStr<N> { fn test() { test_bake!(TinyAsciiStr<10>, const: crate::tinystr!(10usize, "foo"), tinystr); } + +#[test] +fn test_unvalidated() { + test_bake!(UnvalidatedTinyAsciiStr<10>, const: crate::tinystr!(10usize, "foo").to_unvalidated(), tinystr); + test_bake!(UnvalidatedTinyAsciiStr<3>, const: crate::UnvalidatedTinyAsciiStr::from_bytes_unchecked(*b"AB\xCD"), tinystr); +} diff --git a/vendor/tinystr/src/lib.rs b/vendor/tinystr/src/lib.rs index 7745da0e5..3d13e95ea 100644 --- a/vendor/tinystr/src/lib.rs +++ b/vendor/tinystr/src/lib.rs @@ -72,6 +72,7 @@ mod ascii; mod asciibyte; mod error; mod int_ops; +mod unvalidated; #[cfg(feature = "serde")] mod serde; @@ -87,6 +88,7 @@ extern crate alloc; pub use ascii::TinyAsciiStr; pub use error::TinyStrError; +pub use unvalidated::UnvalidatedTinyAsciiStr; /// These are temporary compatability reexports that will be removed /// in a future version. diff --git a/vendor/tinystr/src/serde.rs b/vendor/tinystr/src/serde.rs index 933491f17..4c3f8be13 100644 --- a/vendor/tinystr/src/serde.rs +++ b/vendor/tinystr/src/serde.rs @@ -46,7 +46,7 @@ impl<'de, const N: usize> Visitor<'de> for TinyAsciiStrVisitor<N> { type Value = TinyAsciiStr<N>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a TinyAsciiStr<{}>", N) + write!(formatter, "a TinyAsciiStr<{N}>") } #[inline] diff --git a/vendor/tinystr/src/ule.rs b/vendor/tinystr/src/ule.rs index 0fa212095..eda43890b 100644 --- a/vendor/tinystr/src/ule.rs +++ b/vendor/tinystr/src/ule.rs @@ -2,20 +2,20 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). -use crate::TinyAsciiStr; +use crate::{TinyAsciiStr, UnvalidatedTinyAsciiStr}; use zerovec::maps::ZeroMapKV; use zerovec::ule::*; use zerovec::{ZeroSlice, ZeroVec}; // Safety (based on the safety checklist on the ULE trait): -// 1. CharULE does not include any uninitialized or padding bytes. +// 1. TinyAsciiStr does not include any uninitialized or padding bytes. // (achieved by `#[repr(transparent)]` on a type that satisfies this invariant) -// 2. CharULE is aligned to 1 byte. +// 2. TinyAsciiStr is aligned to 1 byte. // (achieved by `#[repr(transparent)]` on a type that satisfies this invariant) // 3. The impl of validate_byte_slice() returns an error if any byte is not valid. // 4. The impl of validate_byte_slice() returns an error if there are extra bytes. // 5. The other ULE methods use the default impl. -// 6. CharULE byte equality is semantic equality +// 6. TinyAsciiStr byte equality is semantic equality unsafe impl<const N: usize> ULE for TinyAsciiStr<N> { #[inline] fn validate_byte_slice(bytes: &[u8]) -> Result<(), ZeroVecError> { @@ -52,6 +52,46 @@ impl<'a, const N: usize> ZeroMapKV<'a> for TinyAsciiStr<N> { type OwnedType = TinyAsciiStr<N>; } +// Safety (based on the safety checklist on the ULE trait): +// 1. UnvalidatedTinyAsciiStr does not include any uninitialized or padding bytes. +// (achieved by `#[repr(transparent)]` on a type that satisfies this invariant) +// 2. UnvalidatedTinyAsciiStr is aligned to 1 byte. +// (achieved by `#[repr(transparent)]` on a type that satisfies this invariant) +// 3. The impl of validate_byte_slice() returns an error if any byte is not valid. +// 4. The impl of validate_byte_slice() returns an error if there are extra bytes. +// 5. The other ULE methods use the default impl. +// 6. UnvalidatedTinyAsciiStr byte equality is semantic equality +unsafe impl<const N: usize> ULE for UnvalidatedTinyAsciiStr<N> { + #[inline] + fn validate_byte_slice(bytes: &[u8]) -> Result<(), ZeroVecError> { + if bytes.len() % N != 0 { + return Err(ZeroVecError::length::<Self>(bytes.len())); + } + Ok(()) + } +} + +impl<const N: usize> AsULE for UnvalidatedTinyAsciiStr<N> { + type ULE = Self; + + #[inline] + fn to_unaligned(self) -> Self::ULE { + self + } + + #[inline] + fn from_unaligned(unaligned: Self::ULE) -> Self { + unaligned + } +} + +impl<'a, const N: usize> ZeroMapKV<'a> for UnvalidatedTinyAsciiStr<N> { + type Container = ZeroVec<'a, UnvalidatedTinyAsciiStr<N>>; + type Slice = ZeroSlice<UnvalidatedTinyAsciiStr<N>>; + type GetType = UnvalidatedTinyAsciiStr<N>; + type OwnedType = UnvalidatedTinyAsciiStr<N>; +} + #[cfg(test)] mod test { use crate::*; diff --git a/vendor/tinystr/src/unvalidated.rs b/vendor/tinystr/src/unvalidated.rs new file mode 100644 index 000000000..2fffbbc11 --- /dev/null +++ b/vendor/tinystr/src/unvalidated.rs @@ -0,0 +1,104 @@ +// 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 crate::TinyAsciiStr; +use crate::TinyStrError; + +/// A fixed-length bytes array that is expected to be an ASCII string but does not enforce that invariant. +/// +/// Use this type instead of `TinyAsciiStr` if you don't need to enforce ASCII during deserialization. For +/// example, strings that are keys of a map don't need to ever be reified as `TinyAsciiStr`s. +/// +/// The main advantage of this type over `[u8; N]` is that it serializes as a string in +/// human-readable formats like JSON. +#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy)] +pub struct UnvalidatedTinyAsciiStr<const N: usize>(pub(crate) [u8; N]); + +impl<const N: usize> UnvalidatedTinyAsciiStr<N> { + #[inline] + // Converts into a [`TinyAsciiStr`]. Fails if the bytes are not valid ASCII. + pub fn try_into_tinystr(&self) -> Result<TinyAsciiStr<N>, TinyStrError> { + TinyAsciiStr::try_from_raw(self.0) + } + + #[doc(hidden)] + pub const fn from_bytes_unchecked(bytes: [u8; N]) -> Self { + Self(bytes) + } +} + +impl<const N: usize> TinyAsciiStr<N> { + #[inline] + // Converts into a [`UnvalidatedTinyAsciiStr`] + pub const fn to_unvalidated(self) -> UnvalidatedTinyAsciiStr<N> { + UnvalidatedTinyAsciiStr(*self.all_bytes()) + } +} + +#[cfg(feature = "serde")] +impl<const N: usize> serde::Serialize for UnvalidatedTinyAsciiStr<N> { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + use serde::ser::Error; + self.try_into_tinystr() + .map_err(|_| S::Error::custom("invalid ascii in UnvalidatedTinyAsciiStr"))? + .serialize(serializer) + } +} + +macro_rules! deserialize { + ($size:literal) => { + #[cfg(feature = "serde")] + impl<'de, 'a> serde::Deserialize<'de> for UnvalidatedTinyAsciiStr<$size> + where + 'de: 'a, + { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: serde::Deserializer<'de>, + { + if deserializer.is_human_readable() { + Ok(TinyAsciiStr::deserialize(deserializer)?.to_unvalidated()) + } else { + Ok(Self(<[u8; $size]>::deserialize(deserializer)?)) + } + } + } + }; +} + +deserialize!(1); +deserialize!(2); +deserialize!(3); +deserialize!(4); +deserialize!(5); +deserialize!(6); +deserialize!(7); +deserialize!(8); +deserialize!(9); +deserialize!(10); +deserialize!(11); +deserialize!(12); +deserialize!(13); +deserialize!(14); +deserialize!(15); +deserialize!(16); +deserialize!(17); +deserialize!(18); +deserialize!(19); +deserialize!(20); +deserialize!(21); +deserialize!(22); +deserialize!(23); +deserialize!(24); +deserialize!(25); +deserialize!(26); +deserialize!(27); +deserialize!(28); +deserialize!(29); +deserialize!(30); +deserialize!(31); +deserialize!(32); |