use crate::metadata::{IoTypeMetadataKind, MAX_METADATA_CAPACITY, concat_metadata_sources};
use crate::trivial_type::TrivialType;
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct FixedCapacityBytesU8<const CAPACITY: usize> {
len: u8,
bytes: [u8; CAPACITY],
}
impl<const CAPACITY: usize> Default for FixedCapacityBytesU8<CAPACITY> {
#[inline(always)]
fn default() -> Self {
Self {
len: 0,
bytes: [0; CAPACITY],
}
}
}
unsafe impl<const CAPACITY: usize> TrivialType for FixedCapacityBytesU8<CAPACITY> {
const METADATA: &[u8] = {
#[inline(always)]
const fn metadata(capacity: usize) -> ([u8; MAX_METADATA_CAPACITY], usize) {
assert!(
capacity <= u8::MAX as usize,
"`FixedCapacityBytesU8` capacity must not exceed `u8::MAX`"
);
concat_metadata_sources(&[&[
IoTypeMetadataKind::FixedCapacityBytes8b as u8,
capacity as u8,
]])
}
metadata(CAPACITY).0.split_at(metadata(CAPACITY).1).0
};
}
impl<const CAPACITY: usize> FixedCapacityBytesU8<CAPACITY> {
#[inline(always)]
pub fn try_from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() > CAPACITY {
return None;
}
Some(Self {
len: bytes.len() as u8,
bytes: {
let mut buffer = [0; CAPACITY];
buffer[..bytes.len()].copy_from_slice(bytes);
buffer
},
})
}
#[inline(always)]
pub fn get_bytes(&self) -> &[u8] {
&self.bytes[..self.len as usize]
}
#[inline(always)]
pub fn get_bytes_mut(&mut self) -> &mut [u8] {
&mut self.bytes[..self.len as usize]
}
#[inline(always)]
pub const fn len(&self) -> u8 {
self.len
}
#[inline(always)]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
#[inline(always)]
#[must_use = "Operation may fail"]
pub fn append(&mut self, bytes: &[u8]) -> bool {
let len = self.len();
if bytes.len() + len as usize > CAPACITY {
return false;
}
self.bytes[..bytes.len()].copy_from_slice(bytes);
true
}
#[inline(always)]
#[must_use = "Operation may fail"]
pub fn truncate(&mut self, new_len: u8) -> bool {
if new_len > self.len() {
return false;
}
self.len = new_len;
true
}
#[inline(always)]
#[must_use = "Operation may fail"]
pub fn copy_from<T>(&mut self, src: &[u8]) -> bool {
if src.len() > CAPACITY {
return false;
}
self.bytes[..src.len()].copy_from_slice(src);
self.len = src.len() as u8;
true
}
}
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct FixedCapacityBytesU16<const CAPACITY: usize> {
len: u16,
bytes: [u8; CAPACITY],
}
impl<const CAPACITY: usize> Default for FixedCapacityBytesU16<CAPACITY> {
#[inline(always)]
fn default() -> Self {
Self {
len: 0,
bytes: [0; CAPACITY],
}
}
}
unsafe impl<const CAPACITY: usize> TrivialType for FixedCapacityBytesU16<CAPACITY> {
const METADATA: &[u8] = {
#[inline(always)]
const fn metadata(capacity: usize) -> ([u8; MAX_METADATA_CAPACITY], usize) {
assert!(
capacity <= u16::MAX as usize,
"`FixedCapacityBytesU16` capacity must not exceed `u16::MAX`"
);
concat_metadata_sources(&[
&[IoTypeMetadataKind::FixedCapacityBytes16b as u8],
&(capacity as u16).to_le_bytes(),
])
}
metadata(CAPACITY).0.split_at(metadata(CAPACITY).1).0
};
}
impl<const CAPACITY: usize> FixedCapacityBytesU16<CAPACITY> {
#[inline(always)]
pub fn try_from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() > CAPACITY {
return None;
}
Some(Self {
len: bytes.len() as u16,
bytes: {
let mut buffer = [0; CAPACITY];
buffer[..bytes.len()].copy_from_slice(bytes);
buffer
},
})
}
#[inline(always)]
pub fn get_bytes(&self) -> &[u8] {
&self.bytes[..self.len as usize]
}
#[inline(always)]
pub fn get_bytes_mut(&mut self) -> &mut [u8] {
&mut self.bytes[..self.len as usize]
}
#[inline(always)]
pub const fn len(&self) -> u16 {
self.len
}
#[inline(always)]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
#[inline(always)]
#[must_use = "Operation may fail"]
pub fn append(&mut self, bytes: &[u8]) -> bool {
let len = self.len();
if bytes.len() + len as usize > CAPACITY {
return false;
}
self.bytes[..bytes.len()].copy_from_slice(bytes);
true
}
#[inline(always)]
#[must_use = "Operation may fail"]
pub fn truncate(&mut self, new_len: u16) -> bool {
if new_len > self.len() {
return false;
}
self.len = new_len;
true
}
#[inline(always)]
#[must_use = "Operation may fail"]
pub fn copy_from<T>(&mut self, src: &[u8]) -> bool {
if src.len() > CAPACITY {
return false;
}
self.bytes[..src.len()].copy_from_slice(src);
self.len = src.len() as u16;
true
}
}