use super::*;
use crate::varzerovec::lengthless::VarZeroLengthlessSlice;
use crate::vecs::VarZeroVecFormat;
#[cfg(doc)]
use crate::VarZeroSlice;
use core::fmt;
#[derive(PartialEq, Eq)]
#[repr(transparent)]
pub struct MultiFieldsULE<const LEN: usize, Format: VarZeroVecFormat>(
VarZeroLengthlessSlice<[u8], Format>,
);
impl<const LEN: usize, Format: VarZeroVecFormat> MultiFieldsULE<LEN, Format> {
#[inline]
#[expect(clippy::expect_used)] pub fn compute_encoded_len_for(lengths: [usize; LEN]) -> usize {
let lengths = lengths.map(BlankSliceEncoder);
crate::varzerovec::components::compute_serializable_len_without_length::<_, _, Format>(
&lengths,
)
.expect("Too many bytes to encode") as usize
}
pub fn new_from_lengths_partially_initialized<'a>(
lengths: [usize; LEN],
output: &'a mut [u8],
) -> &'a mut Self {
let lengths = lengths.map(BlankSliceEncoder);
crate::varzerovec::components::write_serializable_bytes_without_length::<_, _, Format>(
&lengths, output,
);
debug_assert!(
<VarZeroLengthlessSlice<[u8], Format>>::parse_bytes(LEN as u32, output).is_ok(),
"Encoded slice must be valid VarZeroSlice"
);
unsafe {
let slice = VarZeroLengthlessSlice::<[u8], Format>::from_bytes_unchecked_mut(output);
&mut *(slice as *mut VarZeroLengthlessSlice<[u8], Format>
as *mut MultiFieldsULE<LEN, Format>)
}
}
#[inline]
pub unsafe fn set_field_at<T: VarULE + ?Sized, A: EncodeAsVarULE<T> + ?Sized>(
&mut self,
idx: usize,
value: &A,
) {
value.encode_var_ule_write(self.0.get_bytes_at_mut(LEN as u32, idx))
}
#[inline]
pub unsafe fn validate_field<T: VarULE + ?Sized>(&self, index: usize) -> Result<(), UleError> {
T::validate_bytes(self.0.get_unchecked(LEN as u32, index))
}
#[inline]
pub unsafe fn get_field<T: VarULE + ?Sized>(&self, index: usize) -> &T {
T::from_bytes_unchecked(self.0.get_unchecked(LEN as u32, index))
}
#[inline]
pub unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
let slice = VarZeroLengthlessSlice::<[u8], Format>::from_bytes_unchecked(bytes);
&*(slice as *const VarZeroLengthlessSlice<[u8], Format>
as *const MultiFieldsULE<LEN, Format>)
}
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
}
impl<const LEN: usize, Format: VarZeroVecFormat> fmt::Debug for MultiFieldsULE<LEN, Format> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "MultiFieldsULE<{LEN}>({:?})", self.0.as_bytes())
}
}
#[repr(transparent)]
struct BlankSliceEncoder(usize);
unsafe impl EncodeAsVarULE<[u8]> for BlankSliceEncoder {
fn encode_var_ule_as_slices<R>(&self, _: impl FnOnce(&[&[u8]]) -> R) -> R {
unreachable!()
}
#[inline]
fn encode_var_ule_len(&self) -> usize {
self.0
}
#[inline]
fn encode_var_ule_write(&self, _dst: &mut [u8]) {
}
}
unsafe impl<const LEN: usize, Format: VarZeroVecFormat> VarULE for MultiFieldsULE<LEN, Format> {
#[inline]
fn validate_bytes(slice: &[u8]) -> Result<(), UleError> {
VarZeroLengthlessSlice::<[u8], Format>::parse_bytes(LEN as u32, slice).map(|_| ())
}
#[inline]
unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
let slice = VarZeroLengthlessSlice::<[u8], Format>::from_bytes_unchecked(bytes);
&*(slice as *const VarZeroLengthlessSlice<[u8], Format>
as *const MultiFieldsULE<LEN, Format>)
}
}