use crate::{ByteCursor, IndexOutOfBounds, NotEnoughSpace};
use crate::{is, unwrap, whilst, write_at};
impl<'a> ByteCursor<&'a mut [u8]> {
#[must_use]
#[inline(always)]
pub const fn new(storage: &'a mut [u8]) -> Self {
Self { storage, pos: 0 }
}
#[must_use]
#[inline(always)]
pub const fn writer(storage: &'a mut [u8]) -> Self {
Self::new(storage)
}
#[must_use]
#[inline(always)]
pub const fn at(storage: &'a mut [u8], pos: usize) -> Self {
Self { storage, pos }
}
#[must_use]
#[inline(always)]
pub const fn as_slice(&self) -> &[u8] {
self.storage
}
#[must_use]
#[inline(always)]
pub const fn as_mut_slice(&mut self) -> &mut [u8] {
self.storage
}
#[must_use]
#[inline(always)]
pub const fn len(&self) -> usize {
self.storage.len()
}
#[must_use]
#[inline(always)]
pub const fn is_empty(&self) -> bool {
self.storage.is_empty()
}
#[must_use]
#[inline(always)]
pub const fn remaining_len(&self) -> usize {
let len = self.storage.len();
len.saturating_sub(self.pos)
}
#[must_use]
#[inline(always)]
pub const fn can_write(&self, len: usize) -> bool {
self.can_write_at(self.pos, len)
}
#[must_use]
#[inline(always)]
pub const fn can_write_at(&self, pos: usize, len: usize) -> bool {
let total = self.storage.len();
pos <= total && len <= total - pos
}
#[inline(always)]
pub const fn try_set_pos(&mut self, pos: usize) -> Result<(), IndexOutOfBounds> {
if pos <= self.storage.len() {
self.pos = pos;
Ok(())
} else {
Err(IndexOutOfBounds(Some(pos)))
}
}
#[inline(always)]
pub const fn set_pos_clamped(&mut self, pos: usize) -> usize {
let len = self.storage.len();
self.pos = if pos <= len { pos } else { len };
self.pos
}
#[inline(always)]
pub const fn advance(&mut self, len: usize) -> usize {
let total = self.storage.len();
if self.pos > total {
self.pos = total;
return self.pos;
}
let rem = total - self.pos;
self.pos += if len <= rem { len } else { rem };
self.pos
}
#[inline(always)]
pub const fn skip_exact(&mut self, len: usize) -> Result<(), NotEnoughSpace> {
if self.can_write(len) {
self.pos += len;
Ok(())
} else {
Err(NotEnoughSpace(Some(len)))
}
}
#[inline]
pub const fn write(&mut self, bytes: &[u8]) -> Result<(), NotEnoughSpace> {
let len = bytes.len();
is! { !self.can_write(len), return Err(NotEnoughSpace(Some(len))) }
let start = self.pos;
whilst! { i in 0..len; { self.storage[start + i] = bytes[i]; }}
self.pos += len;
Ok(())
}
#[inline(always)]
pub const fn write_u8(&mut self, byte: u8) -> Result<(), NotEnoughSpace> {
if self.can_write(1) {
write_at![self.storage, +=self.pos, byte];
Ok(())
} else {
Err(NotEnoughSpace(Some(1)))
}
}
#[inline(always)]
pub const fn write_2(&mut self, bytes: [u8; 2]) -> Result<(), NotEnoughSpace> {
unwrap![ok? self.write_at_2(self.pos, bytes)];
self.pos += 2;
Ok(())
}
#[inline(always)]
pub const fn write_4(&mut self, bytes: [u8; 4]) -> Result<(), NotEnoughSpace> {
unwrap![ok? self.write_at_4(self.pos, bytes)];
self.pos += 4;
Ok(())
}
#[inline(always)]
pub const fn write_8(&mut self, bytes: [u8; 8]) -> Result<(), NotEnoughSpace> {
unwrap![ok? self.write_at_8(self.pos, bytes)];
self.pos += 8;
Ok(())
}
#[inline(always)]
pub const fn write_u16_le(&mut self, value: u16) -> Result<(), NotEnoughSpace> {
self.write_2(value.to_le_bytes())
}
#[inline(always)]
pub const fn write_u16_be(&mut self, value: u16) -> Result<(), NotEnoughSpace> {
self.write_2(value.to_be_bytes())
}
#[inline(always)]
pub const fn write_u32_le(&mut self, value: u32) -> Result<(), NotEnoughSpace> {
self.write_4(value.to_le_bytes())
}
#[inline(always)]
pub const fn write_u32_be(&mut self, value: u32) -> Result<(), NotEnoughSpace> {
self.write_4(value.to_be_bytes())
}
#[inline(always)]
pub const fn write_u64_le(&mut self, value: u64) -> Result<(), NotEnoughSpace> {
self.write_8(value.to_le_bytes())
}
#[inline(always)]
pub const fn write_u64_be(&mut self, value: u64) -> Result<(), NotEnoughSpace> {
self.write_8(value.to_be_bytes())
}
#[inline]
pub const fn write_at(&mut self, pos: usize, bytes: &[u8]) -> Result<(), NotEnoughSpace> {
let len = bytes.len();
is! { !self.can_write_at(pos, len), return Err(NotEnoughSpace(Some(len))) }
whilst! { i in 0..len; { self.storage[pos + i] = bytes[i]; }}
Ok(())
}
#[inline(always)]
pub const fn write_at_2(&mut self, pos: usize, bytes: [u8; 2]) -> Result<(), NotEnoughSpace> {
if self.can_write_at(pos, 2) {
write_at![self.storage, pos, @2 bytes];
Ok(())
} else {
Err(NotEnoughSpace(Some(2)))
}
}
#[inline(always)]
pub const fn write_at_4(&mut self, pos: usize, bytes: [u8; 4]) -> Result<(), NotEnoughSpace> {
if self.can_write_at(pos, 4) {
write_at![self.storage, pos, @4 bytes];
Ok(())
} else {
Err(NotEnoughSpace(Some(4)))
}
}
#[inline(always)]
pub const fn write_at_8(&mut self, pos: usize, bytes: [u8; 8]) -> Result<(), NotEnoughSpace> {
if self.can_write_at(pos, 8) {
write_at![self.storage, pos, @8 bytes];
Ok(())
} else {
Err(NotEnoughSpace(Some(8)))
}
}
#[inline(always)]
pub const fn write_at_u32_le(&mut self, pos: usize, value: u32) -> Result<(), NotEnoughSpace> {
self.write_at_4(pos, value.to_le_bytes())
}
#[inline(always)]
pub const fn write_at_u32_be(&mut self, pos: usize, value: u32) -> Result<(), NotEnoughSpace> {
self.write_at_4(pos, value.to_be_bytes())
}
}