Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions components/pattern/src/frontend/zerovec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ where
/// 5. The implementation of `from_bytes_unchecked()` returns a reference to the same data.
/// 6. `parse_bytes()` is equivalent to `validate_bytes()` followed by `from_bytes_unchecked()`.
/// 7. `Pattern<B>` byte equality is semantic equality.
/// 8. There are no concrete methods with the same name as VarULE trait methods.
unsafe impl<B, S: ?Sized + VarULE> VarULE for Pattern<B>
where
B: PatternBackend<Store = S>,
Expand Down
2 changes: 2 additions & 0 deletions components/plurals/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@ impl<V: VarULE + ?Sized> ToOwned for PluralElementsPackedULE<V> {
// 5. The impl of `from_bytes_unchecked()` returns a reference to the same data.
// 6. `parse_bytes()` is equivalent to `validate_bytes()` followed by `from_bytes_unchecked()`
// 7. byte equality is semantic equality
// 8. Concrete methods with the same name as VarULE trait methods have the same behavior as the trait methods.
unsafe impl<V> VarULE for PluralElementsPackedULE<V>
where
V: VarULE + ?Sized,
Expand Down Expand Up @@ -478,6 +479,7 @@ where
///
/// The bytes must be valid according to [`PluralElementsPackedULE::validate_bytes`].
pub const unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
// *Safety:* The behavior of this function is a VarULE safety requirement!
// Safety: the bytes are valid by trait invariant, and we are transparent over bytes
core::mem::transmute(bytes)
}
Expand Down
2 changes: 2 additions & 0 deletions utils/potential_utf/src/ustr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ impl PotentialUtf8 {
/// Get the bytes from a [`PotentialUtf8].
#[inline]
pub const fn as_bytes(&self) -> &[u8] {
// *Safety:* The behavior of this function is a VarULE safety requirement!
&self.0
}

Expand Down Expand Up @@ -177,6 +178,7 @@ impl<'a> zerovec::maps::ZeroMapKV<'a> for PotentialUtf8 {
// 5. The impl of `from_bytes_unchecked()` returns a reference to the same data (returns the argument directly)
// 6. All other methods are defaulted
// 7. `[T]` byte equality is semantic equality (transparent over a ULE)
// 8. Concrete methods with the same name as VarULE trait methods have the same behavior as the trait methods.
/// This impl requires enabling the optional `zerovec` Cargo feature
#[cfg(feature = "zerovec")]
unsafe impl zerovec::ule::VarULE for PotentialUtf8 {
Expand Down
2 changes: 2 additions & 0 deletions utils/zerotrie/src/zerotrie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ macro_rules! impl_zerotrie_subtype {
/// Returns the bytes contained in the underlying store.
#[inline]
pub fn as_bytes(&self) -> &[u8] {
// *Safety:* The behavior of this function is a VarULE safety requirement!
self.store.as_ref()
}
/// Returns this trie as a reference transparent over a byte slice.
Expand Down Expand Up @@ -657,6 +658,7 @@ macro_rules! impl_zerotrie_subtype {
// 5. The impl of `from_bytes_unchecked()` returns a reference to the same data.
// 6. `parse_bytes()` is left to its default impl
// 7. byte equality is semantic equality
// 8. Concrete methods with the same name as VarULE trait methods have the same behavior as the trait methods.
#[cfg(feature = "zerovec")]
unsafe impl<Store> zerovec::ule::VarULE for $name<Store>
where
Expand Down
2 changes: 2 additions & 0 deletions utils/zerovec/src/ule/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ where
/// 6. All other methods *must* be left with their default impl, or else implemented according to
/// their respective safety guidelines.
/// 7. Acknowledge the following note about the equality invariant.
/// 8. If the type implements any concrete methods with the same name as the methods on VarULE,
/// they have identical behavior to the corresponding VarULE methods.
///
/// If the ULE type is a struct only containing other ULE/VarULE types (or other types which satisfy invariants 1 and 2,
/// like `[u8; N]`), invariants 1 and 2 can be achieved via `#[repr(C, packed)]` or `#[repr(transparent)]`.
Expand Down
3 changes: 3 additions & 0 deletions utils/zerovec/src/ule/multi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,14 @@ impl<const LEN: usize, Format: VarZeroVecFormat> MultiFieldsULE<LEN, Format> {
/// - byte slice must be a valid VarZeroLengthlessSlice<[u8], Format> with length LEN
#[inline]
pub unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
// *Safety:* The behavior of this function is a VarULE safety requirement!
// &Self is transparent over &VZS<..> with the right format
mem::transmute(<VarZeroLengthlessSlice<[u8], Format>>::from_bytes_unchecked(bytes))
}

/// Get the bytes behind this value
pub fn as_bytes(&self) -> &[u8] {
// *Safety:* The behavior of this function is a VarULE safety requirement!
self.0.as_bytes()
}
}
Expand Down Expand Up @@ -141,6 +143,7 @@ unsafe impl EncodeAsVarULE<[u8]> for BlankSliceEncoder {
// 5. The impl of `from_bytes_unchecked()` returns a reference to the same data.
// 6. All other methods are defaulted
// 7. `MultiFieldsULE` byte equality is semantic equality (achieved by being transparent over a VarULE type)
// 8. Concrete methods with the same name as VarULE trait methods have the same behavior as the trait methods.
unsafe impl<const LEN: usize, Format: VarZeroVecFormat> VarULE for MultiFieldsULE<LEN, Format> {
/// Note: MultiFieldsULE is usually used in cases where one should be calling .validate_field() directly for
/// each field, rather than using the regular VarULE impl.
Expand Down
1 change: 1 addition & 0 deletions utils/zerovec/src/ule/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ impl<U: VarULE + ?Sized + core::fmt::Debug> core::fmt::Debug for OptionVarULE<U>
// 5. The impl of `from_bytes_unchecked()` returns a reference to the same data.
// 6. All other methods are defaulted
// 7. OptionVarULE<T> byte equality is semantic equality (achieved by being an aggregate)
// 8. There are no concrete methods with the same name as VarULE trait methods.
unsafe impl<U: VarULE + ?Sized> VarULE for OptionVarULE<U> {
#[inline]
fn validate_bytes(slice: &[u8]) -> Result<(), UleError> {
Expand Down
12 changes: 12 additions & 0 deletions utils/zerovec/src/ule/slices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ unsafe impl<T: EqULE, const N: usize> EqULE for [T; N] {}
// 5. The impl of `from_bytes_unchecked()` returns a reference to the same data.
// 6. `parse_bytes()` is equivalent to `validate_bytes()` followed by `from_bytes_unchecked()`
// 7. str byte equality is semantic equality
// 8. The only function on `str` with the same name as a VarULE trait method is `as_bytes()`,
// and the VarULE method is implemented on top of the concrete function.
unsafe impl VarULE for str {
#[inline]
fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> {
Expand All @@ -58,6 +60,12 @@ unsafe impl VarULE for str {
unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
core::str::from_utf8_unchecked(bytes)
}
#[inline]
fn as_bytes(&self) -> &[u8] {
// Safety: str as_bytes() casts the incoming pointer.
// *Safety:* The behavior of this function is a VarULE safety requirement!
self.as_bytes()
}
}

/// Note: VarULE is well-defined for all `[T]` where `T: ULE`, but [`ZeroSlice`] is more ergonomic
Expand Down Expand Up @@ -86,6 +94,10 @@ unsafe impl VarULE for str {
// 5. The impl of `from_bytes_unchecked()` returns a reference to the same data.
// 6. All other methods are defaulted
// 7. `[T]` byte equality is semantic equality (achieved by being a slice of a ULE type)
// 8. There are no methods generically on [T] that have the same name as the VarULE functions.
// However, there are some functions on specific [T] that have the same name:
// - [AsciiChar]::as_bytes() has the correct behavior.
// - [MaybeUninit<T>]::as_bytes() has the correct behavior, though the return value is different.
unsafe impl<T> VarULE for [T]
where
T: ULE,
Expand Down
1 change: 1 addition & 0 deletions utils/zerovec/src/ule/tuplevar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ macro_rules! tuple_varule {
// 5. `from_bytes_unchecked` returns a fat pointer to the bytes.
// 6. All other methods are left at their default impl.
// 7. The inner ULEs have byte equality, so this composition has byte equality.
// 8. There are no concrete methods with the same name as VarULE trait methods.
unsafe impl<$($T: VarULE + ?Sized,)+ Format: VarZeroVecFormat> VarULE for $name<$($T,)+ Format>
{
fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> {
Expand Down
1 change: 1 addition & 0 deletions utils/zerovec/src/ule/vartuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ pub struct VarTupleULE<A: AsULE, V: VarULE + ?Sized> {
// 5. `from_bytes_unchecked` returns a fat pointer to the bytes.
// 6. All other methods are left at their default impl.
// 7. The two ULEs have byte equality, so this composition has byte equality.
// 8. There are no concrete methods with the same name as VarULE trait methods.
unsafe impl<A, V> VarULE for VarTupleULE<A, V>
where
A: AsULE + 'static,
Expand Down
4 changes: 4 additions & 0 deletions utils/zerovec/src/varzerovec/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroSlice<T, F> {
///
/// `bytes` need to be an output from [`VarZeroSlice::as_bytes()`].
pub const unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
// *Safety:* The behavior of this function is a VarULE safety requirement!
// self is really just a wrapper around a byte slice
mem::transmute(bytes)
}
Expand Down Expand Up @@ -254,6 +255,7 @@ impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroSlice<T, F> {
/// ```
#[inline]
pub const fn as_bytes(&self) -> &[u8] {
// *Safety:* The behavior of this function is a VarULE safety requirement!
&self.entire_slice
}

Expand All @@ -269,6 +271,7 @@ impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroSlice<T, F> {
///
/// Slices of the right format can be obtained via [`VarZeroSlice::as_bytes()`]
pub fn parse_bytes<'a>(slice: &'a [u8]) -> Result<&'a Self, UleError> {
// *Safety:* The behavior of this function is a VarULE safety requirement!
<Self as VarULE>::parse_bytes(slice)
}
}
Expand Down Expand Up @@ -441,6 +444,7 @@ where
// 5. The impl of `from_bytes_unchecked()` returns a reference to the same data.
// 6. `as_bytes()` is equivalent to a regular transmute of the underlying data
// 7. VarZeroSlice byte equality is semantic equality (relying on the guideline of the underlying VarULE type)
// 8. Concrete methods with the same name as VarULE trait methods have the same behavior as the trait methods.
unsafe impl<T: VarULE + ?Sized + 'static, F: VarZeroVecFormat> VarULE for VarZeroSlice<T, F> {
fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> {
let _: VarZeroVecComponents<T, F> =
Expand Down
4 changes: 4 additions & 0 deletions utils/zerovec/src/zerovec/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ where
/// Attempt to construct a `&ZeroSlice<T>` from a byte slice, returning an error
/// if it's not a valid byte sequence
pub fn parse_bytes(bytes: &[u8]) -> Result<&Self, UleError> {
// *Safety:* The behavior of this function is a VarULE safety requirement!
T::ULE::parse_bytes_to_slice(bytes).map(Self::from_ule_slice)
}

Expand All @@ -65,6 +66,7 @@ where
///
/// `bytes` need to be an output from [`ZeroSlice::as_bytes()`].
pub const unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
// *Safety:* The behavior of this function is a VarULE safety requirement!
// &[u8] and &[T::ULE] are the same slice with different length metadata.
Self::from_ule_slice(core::slice::from_raw_parts(
bytes.as_ptr() as *const T::ULE,
Expand Down Expand Up @@ -115,6 +117,7 @@ where
/// ```
#[inline]
pub fn as_bytes(&self) -> &[u8] {
// *Safety:* The behavior of this function is a VarULE safety requirement!
T::ULE::slice_as_bytes(self.as_ule_slice())
}

Expand Down Expand Up @@ -498,6 +501,7 @@ where
// 5. The impl of `from_bytes_unchecked()` returns a reference to the same data.
// 6. `as_bytes()` and `parse_bytes()` are defaulted
// 7. `[T::ULE]` byte equality is semantic equality (relying on the guideline of the underlying `ULE` type)
// 8. Concrete methods with the same name as VarULE trait methods have the same behavior as the trait methods.
unsafe impl<T: AsULE + 'static> VarULE for ZeroSlice<T> {
#[inline]
fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> {
Expand Down