#![cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::marker::PhantomData;
use core::fmt::{self, Debug, Formatter};
use oct::serdes::{Deserialise, Result, Serialise};
#[cfg_attr(feature = "proc_macro", doc = include_str!("slot_example.md"))]
pub struct Slot<T: ?Sized> {
buf: Vec<u8>,
_object: PhantomData<T>,
}
impl<T: ?Sized> Slot<T> {
const SIZE_UNIT: usize = 128;
#[must_use]
pub const fn new() -> Self {
let buf = Vec::new();
Self { buf, _object: PhantomData }
}
#[must_use]
pub fn with_capacity(mut capacity: usize) -> Self {
capacity = capacity.next_multiple_of(Self::SIZE_UNIT);
let buf = Vec::with_capacity(capacity);
Self { buf, _object: PhantomData }
}
pub fn read(&self) -> Result<T>
where
T: Deserialise + Sized,
{
Deserialise::deserialise(&mut self.as_bytes())
}
pub fn write(&mut self, value: &T) -> Result<()>
where
T: Serialise,
{
self.clear();
Serialise::serialise(value, &mut self.buf)
}
pub fn write_within_capacity(&mut self, value: &T) -> Result<()>
where
T: Serialise,
{
self.clear();
Serialise::serialise(value, &mut self.buf.as_mut_slice())
}
pub fn write_with<F: FnOnce(&mut [u8]) -> Result<usize>>(&mut self, op: F) -> Result<()>
where
T: Serialise,
{
let len = op(self.as_bytes_mut())?;
self.set_len(len);
Ok(())
}
pub fn copy_from_slice(&mut self, data: &[u8]) {
self.buf.resize(data.len(), 0);
self.as_bytes_mut().copy_from_slice(data);
}
pub fn clear(&mut self) {
self.buf.clear()
}
#[inline]
pub fn set_len(&mut self, len: usize) {
assert!(
len <= self.capacity(),
"cannot extend length beyond slot capacity",
);
unsafe { self.set_len_unchecked(len) };
}
#[inline]
pub unsafe fn set_len_unchecked(&mut self, len: usize) {
debug_assert!(len <= self.capacity());
unsafe { self.buf.set_len(len) };
}
#[inline]
#[must_use]
pub fn capacity(&self) -> usize {
self.buf.capacity()
}
#[inline(always)]
#[must_use]
pub fn len(&self) -> usize {
self.buf.len()
}
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
#[must_use]
pub fn as_bytes(&self) -> &[u8] {
self.buf.as_slice()
}
#[inline]
#[must_use]
pub fn as_bytes_mut(&mut self) -> &mut [u8] {
self.buf.as_mut_slice()
}
#[inline(always)]
#[must_use]
pub fn as_ptr(&self) -> *const u8 {
self.buf.as_ptr()
}
#[inline(always)]
#[must_use]
pub fn as_mut_ptr(&mut self) -> *mut u8 {
self.buf.as_mut_ptr()
}
}
impl<T: ?Sized> Clone for Slot<T> {
fn clone(&self) -> Self {
let buf = self.buf.clone();
Self { buf, _object: PhantomData }
}
}
impl<T: ?Sized> Debug for Slot<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let mut debug = f.debug_tuple("Slot");
debug.field(&self.as_bytes());
debug.finish()
}
}
impl<T: ?Sized> Default for Slot<T> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<T: ?Sized> Drop for Slot<T> {
fn drop(&mut self) {}
}