#![doc = include_str!("../README.md")]
#![no_std]
#![deny(missing_docs, unsafe_op_in_unsafe_fn)]
#[cfg(feature = "std")]
extern crate std;
#[cfg(feature = "std")]
pub mod io;
use core::fmt::{self, Debug, Formatter};
use core::mem::MaybeUninit;
use core::ptr::{self, NonNull};
use core::slice;
pub struct BorrowedBuf<'data, T> {
buf: &'data mut [MaybeUninit<T>],
filled: usize,
init: bool,
}
impl<T> Debug for BorrowedBuf<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
BorrowedBufDebug {
init: self.init,
filled: self.filled,
capacity: self.capacity(),
}
.fmt(f)
}
}
struct BorrowedBufDebug {
init: bool,
filled: usize,
capacity: usize,
}
impl Debug for BorrowedBufDebug {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("BorrowedBuf")
.field("init", &self.init)
.field("filled", &self.filled)
.field("capacity", &self.capacity)
.finish()
}
}
impl<'data, T: Copy> From<&'data mut [T]> for BorrowedBuf<'data, T> {
#[inline]
fn from(slice: &'data mut [T]) -> BorrowedBuf<'data, T> {
BorrowedBuf {
buf: unsafe { &mut *(slice as *mut [T] as *mut [MaybeUninit<T>]) },
filled: 0,
init: true,
}
}
}
impl<'data, T: Copy> From<&'data mut [MaybeUninit<T>]> for BorrowedBuf<'data, T> {
#[inline]
fn from(buf: &'data mut [MaybeUninit<T>]) -> BorrowedBuf<'data, T> {
BorrowedBuf {
buf,
filled: 0,
init: false,
}
}
}
impl<'data, T: Copy> From<BorrowedCursor<'data, T>> for BorrowedBuf<'data, T> {
#[inline]
fn from(buf: BorrowedCursor<'data, T>) -> BorrowedBuf<'data, T> {
let filled = buf.filled();
let init = buf.is_buf_init();
let len = buf.buf_len();
BorrowedBuf {
buf: unsafe { slice::from_raw_parts_mut(buf.buf.as_ptr().add(filled), len - filled) },
filled: 0,
init,
}
}
}
impl<'data, T> BorrowedBuf<'data, T> {
#[inline]
pub fn capacity(&self) -> usize {
self.buf.len()
}
#[inline]
#[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize {
self.filled
}
#[inline]
pub fn is_init(&self) -> bool {
self.init
}
}
impl<'data, T: Copy> BorrowedBuf<'data, T> {
#[inline]
pub fn filled(&self) -> &[T] {
unsafe { assume_init_ref(self.buf.get_unchecked(..self.filled)) }
}
#[inline]
pub fn filled_mut(&mut self) -> &mut [T] {
unsafe { assume_init_mut(self.buf.get_unchecked_mut(..self.filled)) }
}
#[inline]
pub fn into_filled(self) -> &'data [T] {
unsafe { assume_init_ref(self.buf.get_unchecked(..self.filled)) }
}
#[inline]
pub fn into_filled_mut(self) -> &'data mut [T] {
unsafe { assume_init_mut(self.buf.get_unchecked_mut(..self.filled)) }
}
#[inline]
pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this, T> {
let borrowed_buf = NonNull::from(&mut *self);
BorrowedCursor {
buf: NonNull::from(&mut *self.buf).cast(),
borrowed_buf,
}
}
#[inline]
pub fn clear(&mut self) -> &mut Self {
self.filled = 0;
self
}
#[inline]
pub fn truncate(&mut self, len: usize) -> &mut Self {
if len < self.filled {
self.filled = len;
}
self
}
#[inline]
pub unsafe fn set_init(&mut self) -> &mut Self {
self.init = true;
self
}
}
pub struct BorrowedCursor<'a, T> {
buf: NonNull<MaybeUninit<T>>,
borrowed_buf: NonNull<BorrowedBuf<'a, T>>,
}
unsafe impl<T: Send> Send for BorrowedCursor<'_, T> {}
unsafe impl<T: Sync> Sync for BorrowedCursor<'_, T> {}
impl<T> Debug for BorrowedCursor<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let buf = BorrowedBufDebug {
init: self.is_buf_init(),
filled: self.filled(),
capacity: self.buf_len(),
};
f.debug_struct("BorrowedCursor").field("buf", &buf).finish()
}
}
impl<'a, T> BorrowedCursor<'a, T> {
#[inline]
fn buf_mut(&mut self) -> &mut [MaybeUninit<T>] {
let len = self.buf_len();
unsafe { slice::from_raw_parts_mut(self.buf.as_ptr(), len) }
}
#[inline]
fn buf_len(&self) -> usize {
unsafe {
let borrowed_buf = self.borrowed_buf.as_ptr();
let buf_ptr: *const &'a mut [MaybeUninit<T>] = &raw const (*borrowed_buf).buf;
let buf_ptr: *const *const [MaybeUninit<T>] = buf_ptr.cast();
let buf: *const [MaybeUninit<T>] = *buf_ptr;
buf.len()
}
}
#[inline]
fn unfilled_slice(&mut self) -> &mut [MaybeUninit<T>] {
let filled = self.filled();
unsafe { self.buf_mut().get_unchecked_mut(filled..) }
}
#[inline]
fn filled(&self) -> usize {
unsafe { (*self.borrowed_buf.as_ptr()).filled }
}
#[inline]
fn is_buf_init(&self) -> bool {
unsafe { (*self.borrowed_buf.as_ptr()).init }
}
#[inline]
unsafe fn set_buf_init(&mut self, init: bool) {
unsafe {
(*self.borrowed_buf.as_ptr()).init = init;
}
}
#[inline]
unsafe fn add_filled(&mut self, n: usize) {
unsafe {
(*self.borrowed_buf.as_ptr()).filled += n;
}
}
}
impl<'a, T: Copy> BorrowedCursor<'a, T> {
#[inline]
pub fn reborrow<'this>(&'this mut self) -> BorrowedCursor<'this, T> {
BorrowedCursor {
buf: self.buf,
borrowed_buf: self.borrowed_buf,
}
}
#[inline]
pub fn capacity(&self) -> usize {
self.buf_len() - self.filled()
}
#[inline]
pub fn written(&self) -> usize {
self.filled()
}
#[inline]
pub fn is_init(&self) -> bool {
self.is_buf_init()
}
#[inline]
pub unsafe fn set_init(&mut self) {
unsafe { self.set_buf_init(true) }
}
#[inline]
pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit<T>] {
self.unfilled_slice()
}
#[inline]
#[track_caller]
pub fn advance_checked(&mut self, n: usize) -> &mut Self {
let init_unfilled = if self.is_buf_init() {
self.buf_len() - self.filled()
} else {
0
};
assert!(
n <= init_unfilled,
"advanced past the initialized part of the buffer"
);
unsafe { self.advance(n) };
self
}
#[inline]
pub unsafe fn advance(&mut self, n: usize) -> &mut Self {
unsafe { self.add_filled(n) };
self
}
#[inline]
#[track_caller]
pub fn append(&mut self, buf: &[T]) {
assert!(
self.capacity() >= buf.len(),
"appended past the end of the buffer"
);
unsafe {
let dst = self.as_mut().as_mut_ptr().cast::<T>();
ptr::copy_nonoverlapping(buf.as_ptr(), dst, buf.len());
}
unsafe { self.advance(buf.len()) };
}
#[inline]
#[track_caller]
pub fn append_fill(&mut self, n: usize, value: T) {
assert!(self.capacity() >= n, "appended past the end of the buffer");
self.unfilled_slice()[..n].fill(MaybeUninit::new(value));
unsafe { self.advance(n) };
}
pub fn with_unfilled_buf<R>(&mut self, f: impl FnOnce(&mut BorrowedBuf<'_, T>) -> R) -> R {
let mut buf = BorrowedBuf::from(self.reborrow());
let prev_ptr = buf.buf as *const _;
let res = f(&mut buf);
assert!(
ptr::eq(prev_ptr, buf.buf),
"the `BorrowedBuf` given to the closure was replaced"
);
let filled = buf.filled;
let init = buf.init;
unsafe {
self.set_buf_init(init);
self.advance(filled);
}
res
}
}
impl<'a, T: Default + Copy> BorrowedCursor<'a, T> {
#[inline]
pub fn ensure_init(&mut self) -> &mut [T] {
if !self.is_buf_init() {
self.unfilled_slice().fill(MaybeUninit::new(T::default()));
unsafe { self.set_buf_init(true) };
}
unsafe { assume_init_mut(self.unfilled_slice()) }
}
}
#[inline(always)]
const unsafe fn assume_init_ref<T>(s: &[MaybeUninit<T>]) -> &[T] {
unsafe { &*(s as *const [MaybeUninit<T>] as *const [T]) }
}
#[inline(always)]
const unsafe fn assume_init_mut<T>(s: &mut [MaybeUninit<T>]) -> &mut [T] {
unsafe { &mut *(s as *mut [MaybeUninit<T>] as *mut [T]) }
}
#[cfg(doctest)]
struct CompileFail;