/// The [`ULE`] types implementing this trait guarantee that [`NicheBytes::NICHE_BIT_PATTERN`] /// can never occur as a valid byte representation of the type. /// /// Guarantees for a valid implementation. /// 1. N must be equal to `core::mem::sizeo_of::<Self>()` or else it will /// cause panics. /// 2. The bit pattern [`NicheBytes::NICHE_BIT_PATTERN`] must not be incorrect as it would lead to /// weird behaviour. /// 3. The abstractions built on top of this trait must panic on an invalid N. /// 4. The abstractions built on this trait that use type punning must ensure that type being /// punned is [`ULE`]. pubtrait NicheBytes<const N: usize> { const NICHE_BIT_PATTERN: [u8; N];
}
/// [`ULE`] type for [`NichedOption<U,N>`] where U implements [`NicheBytes`]. /// The invalid bit pattern is used as the niche. /// /// This uses 1 byte less than [`crate::ule::OptionULE<U>`] to represent [`NichedOption<U,N>`]. /// /// # Example /// /// ``` /// use core::num::NonZeroI8; /// use zerovec::ule::NichedOption; /// use zerovec::ZeroVec; /// /// let bytes = &[0x00, 0x01, 0x02, 0x00]; /// let zv_no: ZeroVec<NichedOption<NonZeroI8, 1>> = /// ZeroVec::parse_byte_slice(bytes) /// .expect("Unable to parse as NichedOption."); /// /// assert_eq!(zv_no.get(0).map(|e| e.0), Some(None)); /// assert_eq!(zv_no.get(1).map(|e| e.0), Some(NonZeroI8::new(1))); /// assert_eq!(zv_no.get(2).map(|e| e.0), Some(NonZeroI8::new(2))); /// assert_eq!(zv_no.get(3).map(|e| e.0), Some(None)); /// ``` // Invariants: // The union stores [`NicheBytes::NICHE_BIT_PATTERN`] when None. // Any other bit pattern is a valid. #[repr(C)] pub union NichedOptionULE<U: NicheBytes<N> + ULE, const N: usize> { /// Invariant: The value is `niche` only if the bytes equal NICHE_BIT_PATTERN.
niche: [u8; N], /// Invariant: The value is `valid` if the `niche` field does not match NICHE_BIT_PATTERN.
valid: U,
}
impl<U: NicheBytes<N> + ULE, const N: usize> NichedOptionULE<U, N> { /// New `NichedOptionULE<U, N>` from `Option<U>` pubfn new(opt: Option<U>) -> Self {
assert!(N == core::mem::size_of::<U>()); match opt {
Some(u) => Self { valid: u },
None => Self {
niche: <U as NicheBytes<N>>::NICHE_BIT_PATTERN,
},
}
}
/// Convert to an `Option<U>` pubfn get(self) -> Option<U> { // Safety: The union stores NICHE_BIT_PATTERN when None otherwise a valid U unsafe { ifself.niche == <U as NicheBytes<N>>::NICHE_BIT_PATTERN {
None
} else {
Some(self.valid)
}
}
}
}
/// Safety for ULE trait /// 1. NichedOptionULE does not have any padding bytes due to `#[repr(C)]` on a struct /// containing only ULE fields. /// NichedOptionULE either contains NICHE_BIT_PATTERN or valid U byte sequences. /// In both cases the data is initialized. /// 2. NichedOptionULE is aligned to 1 byte due to `#[repr(C, packed)]` on a struct containing only /// ULE fields. /// 3. validate_byte_slice impl returns an error if invalid bytes are encountered. /// 4. validate_byte_slice impl returns an error there are extra bytes. /// 5. The other ULE methods are left to their default impl. /// 6. NichedOptionULE equality is based on ULE equality of the subfield, assuming that NicheBytes /// has been implemented correctly (this is a correctness but not a safety guarantee). unsafeimpl<U: NicheBytes<N> + ULE, const N: usize> ULE for NichedOptionULE<U, N> { fn validate_byte_slice(bytes: &[u8]) -> Result<(), crate::ZeroVecError> { let size = size_of::<Self>(); // The implemention is only correct if NICHE_BIT_PATTERN has same number of bytes as the // type.
debug_assert!(N == core::mem::size_of::<U>());
// The bytes should fully transmute to a collection of Self if bytes.len() % size != 0 { return Err(crate::ZeroVecError::length::<Self>(bytes.len()));
}
bytes.chunks(size).try_for_each(|chunk| { // Associated const cannot be referenced in a pattern // https://doc.rust-lang.org/error-index.html#E0158 if chunk == <U as NicheBytes<N>>::NICHE_BIT_PATTERN {
Ok(())
} else {
U::validate_byte_slice(chunk)
}
})
}
}
/// Optional type which uses [`NichedOptionULE<U,N>`] as ULE type. /// The implementors guarantee that `N == core::mem::sizeo_of::<Self>()` /// [`repr(transparent)`] guarantees that the layout is same as [`Option<U>`] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[repr(transparent)] #[non_exhaustive] pubstruct NichedOption<U, const N: usize>(pub Option<U>);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.