use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops::{Deref, DerefMut};
use super::raw::{RawMut, RawSpan};
use super::shared::Shared;
use super::{CapacityError, SpareWriter};
pub(super) const BLOCK_CAPACITY: u32 = 64 * 1024;
pub struct Owned {
raw: RawMut,
len: u32,
}
impl Owned {
pub fn try_with_capacity(capacity: usize) -> Result<Self, CapacityError> {
let capacity =
u32::try_from(capacity).map_err(|_| CapacityError::new(capacity, u32::MAX as usize))?;
Ok(Self::with_capacity_u32(capacity))
}
#[must_use]
#[track_caller]
pub fn with_capacity(capacity: usize) -> Self {
if capacity > u32::MAX as usize {
panic!("buffer capacity overflow: {capacity} > {}", u32::MAX);
}
Self::with_capacity_u32(capacity as u32)
}
#[must_use]
pub fn with_capacity_u32(capacity: u32) -> Self {
Self {
raw: RawMut::with_capacity_u32(capacity),
len: 0,
}
}
#[must_use]
pub fn filled(len: usize, byte: u8) -> Self {
let mut value = Self::with_capacity(len);
value.raw.fill(byte);
value.len = len as u32;
value
}
pub fn capacity(&self) -> usize {
self.raw.capacity()
}
pub fn len(&self) -> usize {
self.len as usize
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn as_slice(&self) -> &[u8] {
self.raw.initialized(self.len())
}
pub fn as_mut_slice(&mut self) -> &mut [u8] {
self.raw.initialized_mut(self.len as usize)
}
pub fn try_extend_from_slice(&mut self, src: &[u8]) -> Result<(), CapacityError> {
let start = self.len();
let end = start + src.len();
let capacity = self.capacity();
if end > capacity {
return Err(CapacityError::new(end, capacity));
}
self.raw.copy_from_slice(start, src);
self.len = end as u32;
Ok(())
}
#[track_caller]
pub fn extend_from_slice(&mut self, src: &[u8]) {
if let Err(error) = self.try_extend_from_slice(src) {
panic!("{error}");
}
}
pub fn try_push(&mut self, byte: u8) -> Result<(), CapacityError> {
let offset = self.len();
let capacity = self.capacity();
if offset == capacity {
return Err(CapacityError::new(offset + 1, capacity));
}
self.raw.write_byte(offset, byte);
self.len += 1;
Ok(())
}
#[track_caller]
pub fn push(&mut self, byte: u8) {
if let Err(error) = self.try_push(byte) {
panic!("{error}");
}
}
pub fn clear(&mut self) {
self.len = 0;
}
pub fn truncate(&mut self, len: usize) {
if len < self.len() {
self.len = len as u32;
}
}
pub fn spare_writer(&mut self) -> SpareWriter<'_> {
self.raw.spare_writer(&mut self.len)
}
#[inline]
#[must_use]
pub fn freeze(self) -> Shared {
let Self { raw, len } = self;
if len == 0 {
return Shared::new();
}
let span = unsafe { RawSpan::new_unchecked(raw.freeze(), 0, len) };
Shared::from_raw_span(span)
}
}
impl Clone for Owned {
fn clone(&self) -> Self {
let mut clone = Self::with_capacity_u32(self.capacity() as u32);
if self.len != 0 {
clone.raw.copy_from_raw(0, &self.raw, 0, self.len());
clone.len = self.len;
}
clone
}
}
impl AsRef<[u8]> for Owned {
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl AsMut<[u8]> for Owned {
fn as_mut(&mut self) -> &mut [u8] {
self.as_mut_slice()
}
}
impl Deref for Owned {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl DerefMut for Owned {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut_slice()
}
}
impl PartialEq for Owned {
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl PartialEq<Block> for Owned {
fn eq(&self, other: &Block) -> bool {
self.as_slice() == other.as_slice()
}
}
impl Eq for Owned {}
impl Hash for Owned {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_slice().hash(state);
}
}
impl fmt::Debug for Owned {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Owned")
.field("len", &self.len())
.field("capacity", &self.capacity())
.finish()
}
}
pub struct Block {
raw: RawMut,
len: u32,
}
impl Block {
pub const CAPACITY: usize = BLOCK_CAPACITY as usize;
#[must_use]
pub fn new() -> Self {
Self {
raw: RawMut::with_capacity_u32(BLOCK_CAPACITY),
len: 0,
}
}
pub fn capacity(&self) -> usize {
Self::CAPACITY
}
pub fn len(&self) -> usize {
self.len as usize
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn as_slice(&self) -> &[u8] {
self.raw.initialized(self.len())
}
pub fn as_mut_slice(&mut self) -> &mut [u8] {
self.raw.initialized_mut(self.len as usize)
}
pub fn try_extend_from_slice(&mut self, src: &[u8]) -> Result<(), CapacityError> {
let start = self.len();
let end = start + src.len();
if end > Self::CAPACITY {
return Err(CapacityError::new(end, Self::CAPACITY));
}
self.raw.copy_from_slice(start, src);
self.len = end as u32;
Ok(())
}
#[track_caller]
pub fn extend_from_slice(&mut self, src: &[u8]) {
if let Err(error) = self.try_extend_from_slice(src) {
panic!("{error}");
}
}
pub fn try_push(&mut self, byte: u8) -> Result<(), CapacityError> {
let offset = self.len();
if offset == Self::CAPACITY {
return Err(CapacityError::new(offset + 1, Self::CAPACITY));
}
self.raw.write_byte(offset, byte);
self.len += 1;
Ok(())
}
#[track_caller]
pub fn push(&mut self, byte: u8) {
if let Err(error) = self.try_push(byte) {
panic!("{error}");
}
}
pub fn clear(&mut self) {
self.len = 0;
}
pub fn truncate(&mut self, len: usize) {
if len < self.len() {
self.len = len as u32;
}
}
pub fn spare_writer(&mut self) -> SpareWriter<'_> {
self.raw.spare_writer(&mut self.len)
}
#[inline]
#[must_use]
pub fn freeze(self) -> Shared {
let Self { raw, len } = self;
if len == 0 {
return Shared::new();
}
let span = unsafe { RawSpan::new_unchecked(raw.freeze(), 0, len) };
Shared::from_raw_span(span)
}
}
impl Default for Block {
fn default() -> Self {
Self::new()
}
}
impl Clone for Block {
fn clone(&self) -> Self {
let mut clone = Self::new();
if self.len != 0 {
clone.raw.copy_from_raw(0, &self.raw, 0, self.len());
clone.len = self.len;
}
clone
}
}
impl AsRef<[u8]> for Block {
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl AsMut<[u8]> for Block {
fn as_mut(&mut self) -> &mut [u8] {
self.as_mut_slice()
}
}
impl Deref for Block {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl DerefMut for Block {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut_slice()
}
}
impl PartialEq for Block {
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl PartialEq<Owned> for Block {
fn eq(&self, other: &Owned) -> bool {
self.as_slice() == other.as_slice()
}
}
impl Eq for Block {}
impl Hash for Block {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_slice().hash(state);
}
}
impl fmt::Debug for Block {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Block").field("len", &self.len()).finish()
}
}