use super::BStackAllocator;
use crate::BStack;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::io;
use std::ops::Range;
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct BStackRange {
offset: u64,
len: u64,
}
impl BStackRange {
#[inline]
pub unsafe fn from_raw_parts(offset: u64, len: u64) -> Self {
Self { offset, len }
}
#[inline]
pub fn new(offset: u64, len: u64) -> Self {
Self {
offset,
len: len.min(u64::MAX - offset),
}
}
#[inline]
pub fn empty() -> Self {
Self { offset: 0, len: 0 }
}
#[inline]
pub fn start(&self) -> u64 {
self.offset
}
#[inline]
pub fn end(&self) -> u64 {
self.offset + self.len
}
#[inline]
pub fn len(&self) -> u64 {
self.len
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn overlaps(&self, other: &Self) -> bool {
!self.is_empty()
&& !other.is_empty()
&& self.offset < other.end()
&& other.offset < self.end()
}
#[inline]
pub fn adjacent_to(&self, other: &Self) -> bool {
self.end() == other.start() || other.end() == self.start()
}
#[inline]
pub fn merge(&self, other: &Self) -> Option<Self> {
if self.is_empty() {
return Some(*other);
}
if other.is_empty() {
return Some(*self);
}
if !self.overlaps(other) {
return None;
}
let start = self.offset.min(other.offset);
let end = self.end().max(other.end());
Some(Self::new(start, end - start))
}
#[inline]
pub fn merge_adjacent(&self, other: &Self) -> Option<Self> {
if self.is_empty() || other.is_empty() || !self.adjacent_to(other) {
return None;
}
let start = self.offset.min(other.offset);
let end = self.end().max(other.end());
Some(Self::new(start, end - start))
}
#[inline]
pub fn range(&self) -> Range<u64> {
self.offset..self.offset + self.len
}
#[inline]
pub fn to_bytes(self) -> [u8; 16] {
let mut out = [0u8; 16];
out[..8].copy_from_slice(&self.offset.to_le_bytes());
out[8..].copy_from_slice(&self.len.to_le_bytes());
out
}
#[inline]
pub fn from_bytes(bytes: [u8; 16]) -> Self {
let offset = u64::from_le_bytes(bytes[..8].try_into().unwrap());
let len = u64::from_le_bytes(bytes[8..].try_into().unwrap());
Self::new(offset, len)
}
}
impl PartialOrd for BStackRange {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for BStackRange {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.offset
.cmp(&other.offset)
.then(self.len.cmp(&other.len))
}
}
impl From<BStackRange> for [u8; 16] {
#[inline]
fn from(r: BStackRange) -> Self {
r.to_bytes()
}
}
impl From<Range<u64>> for BStackRange {
#[inline]
fn from(r: Range<u64>) -> Self {
BStackRange {
offset: r.start,
len: r.end.saturating_sub(r.start),
}
}
}
impl From<BStackRange> for Range<u64> {
#[inline]
fn from(range: BStackRange) -> Self {
range.offset..range.offset + range.len
}
}
impl fmt::Debug for BStackRange {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BStackRange")
.field("start", &self.start())
.field("end", &self.end())
.field("len", &self.len())
.finish_non_exhaustive()
}
}
pub struct BStackSlice<'a> {
stack: &'a BStack,
range: BStackRange,
}
impl<'a> Clone for BStackSlice<'a> {
#[inline]
fn clone(&self) -> Self {
BStackSlice {
stack: self.stack,
range: self.range,
}
}
}
impl<'a> fmt::Debug for BStackSlice<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BStackSlice")
.field("start", &self.start())
.field("end", &self.end())
.field("len", &self.len())
.finish_non_exhaustive()
}
}
impl<'a> BStackSlice<'a> {
#[inline]
pub unsafe fn from_raw_parts(stack: &'a BStack, offset: u64, len: u64) -> Self {
Self {
stack,
range: unsafe { BStackRange::from_raw_parts(offset, len) },
}
}
#[inline]
pub unsafe fn from_raw_range(stack: &'a BStack, range: BStackRange) -> Self {
Self { stack, range }
}
#[inline]
pub fn empty(stack: &'a BStack) -> Self {
Self {
stack,
range: BStackRange::empty(),
}
}
#[inline]
pub fn start(&self) -> u64 {
self.range.start()
}
#[inline]
pub fn end(&self) -> u64 {
self.range.end()
}
#[inline]
pub fn len(&self) -> u64 {
self.range.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.range.is_empty()
}
#[inline]
pub fn range(&self) -> Range<u64> {
self.range.range()
}
#[inline]
pub fn as_range(&self) -> BStackRange {
self.range
}
#[inline]
pub fn overlaps(&self, other: &Self) -> bool {
self.range.overlaps(&other.range)
}
#[inline]
pub fn adjacent_to(&self, other: &Self) -> bool {
self.range.adjacent_to(&other.range)
}
#[inline]
pub fn merge(&self, other: &Self) -> Option<Self> {
if !std::ptr::eq(self.stack, other.stack) {
return None;
}
self.range.merge(&other.range).map(|range| Self {
stack: self.stack,
range,
})
}
#[inline]
pub fn merge_adjacent(&self, other: &Self) -> Option<Self> {
if !std::ptr::eq(self.stack, other.stack) {
return None;
}
self.range.merge_adjacent(&other.range).map(|range| Self {
stack: self.stack,
range,
})
}
#[inline]
pub fn to_bytes(&self) -> [u8; 16] {
self.range.to_bytes()
}
#[inline]
pub unsafe fn from_bytes(stack: &'a BStack, bytes: [u8; 16]) -> Self {
Self {
stack,
range: BStackRange::from_bytes(bytes),
}
}
#[inline]
pub fn stack(&self) -> &'a BStack {
self.stack
}
#[inline]
pub fn subslice(&self, start: u64, end: u64) -> BStackSlice<'a> {
self.subslice_range(start..end)
}
pub fn subslice_range(&self, range: Range<u64>) -> BStackSlice<'a> {
assert!(range.start <= range.end, "range start must be <= end");
assert!(range.end <= self.len(), "range end must be <= slice length");
BStackSlice {
stack: self.stack,
range: unsafe {
BStackRange::from_raw_parts(self.start() + range.start, range.end - range.start)
},
}
}
#[inline]
pub fn split_at(&self, mid: u64) -> (BStackSlice<'a>, BStackSlice<'a>) {
assert!(mid <= self.len(), "split_at: mid must be <= slice length");
(self.subslice(0, mid), self.subslice(mid, self.len()))
}
#[inline]
pub fn split_at_mut(&mut self, mid: u64) -> (BStackSlice<'a>, BStackSlice<'a>) {
assert!(
mid <= self.len(),
"split_at_mut: mid must be <= slice length"
);
(self.subslice(0, mid), self.subslice(mid, self.len()))
}
#[inline]
pub fn head(&self, n: u64) -> BStackSlice<'a> {
let n = n.min(self.len());
self.subslice(0, n)
}
#[inline]
pub fn tail(&self, n: u64) -> BStackSlice<'a> {
let n = n.min(self.len());
self.subslice(self.len() - n, self.len())
}
#[inline]
pub fn get(&self, index: u64) -> io::Result<Option<u8>> {
if index >= self.len() {
return Ok(None);
}
let mut buf = [0u8; 1];
self.stack.get_into(self.start() + index, &mut buf)?;
Ok(Some(buf[0]))
}
#[inline]
pub fn contains(&self, needle: u8) -> io::Result<bool> {
Ok(self.read()?.contains(&needle))
}
pub fn starts_with(&self, prefix: &[u8]) -> io::Result<bool> {
let n = prefix.len() as u64;
if n > self.len() {
return Ok(false);
}
Ok(self.head(n).read()? == prefix)
}
pub fn ends_with(&self, suffix: &[u8]) -> io::Result<bool> {
let n = suffix.len() as u64;
if n > self.len() {
return Ok(false);
}
Ok(self.tail(n).read()? == suffix)
}
#[inline]
pub fn find(&self, needle: u8) -> io::Result<Option<u64>> {
Ok(self
.read()?
.iter()
.position(|&b| b == needle)
.map(|i| i as u64))
}
#[inline]
pub fn rfind(&self, needle: u8) -> io::Result<Option<u64>> {
Ok(self
.read()?
.iter()
.rposition(|&b| b == needle)
.map(|i| i as u64))
}
#[inline]
pub fn position(&self, predicate: impl Fn(u8) -> bool) -> io::Result<Option<u64>> {
Ok(self
.read()?
.iter()
.position(|&b| predicate(b))
.map(|i| i as u64))
}
#[inline]
pub fn rposition(&self, predicate: impl Fn(u8) -> bool) -> io::Result<Option<u64>> {
Ok(self
.read()?
.iter()
.rposition(|&b| predicate(b))
.map(|i| i as u64))
}
#[inline]
pub fn read(&self) -> io::Result<Vec<u8>> {
self.stack.get(self.start(), self.end())
}
#[inline]
pub fn read_into(&self, buf: &mut [u8]) -> io::Result<()> {
let n = (buf.len() as u64).min(self.len()) as usize;
self.stack.get_into(self.start(), &mut buf[..n])
}
pub fn read_range(&self, start: u64, end: u64) -> io::Result<Vec<u8>> {
if end > self.len() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("range [{start}, {end}) exceeds slice length {}", self.len()),
));
}
self.stack.get(self.start() + start, self.start() + end)
}
pub fn read_range_into(&self, start: u64, buf: &mut [u8]) -> io::Result<()> {
let end_rel = start + buf.len() as u64;
if end_rel > self.len() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"range [{start}, {end_rel}) exceeds slice length {}",
self.len()
),
));
}
self.stack.get_into(self.start() + start, buf)
}
#[cfg(feature = "set")]
pub fn write(&mut self, data: impl AsRef<[u8]>) -> io::Result<()> {
let data = data.as_ref();
let n = (data.len() as u64).min(self.len()) as usize;
self.stack.set(self.start(), &data[..n])
}
#[cfg(feature = "set")]
pub fn write_range(&mut self, start: u64, data: impl AsRef<[u8]>) -> io::Result<()> {
let data = data.as_ref();
let end_rel = start + data.len() as u64;
if end_rel > self.len() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"range [{start}, {end_rel}) exceeds slice length {}",
self.len()
),
));
}
self.stack.set(self.start() + start, data)
}
#[cfg(feature = "set")]
#[inline]
pub fn zero(&mut self) -> io::Result<()> {
self.stack.zero(self.start(), self.len())
}
#[cfg(feature = "set")]
pub fn zero_range(&mut self, start: u64, n: u64) -> io::Result<()> {
let end_rel = start + n;
if end_rel > self.len() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"range [{start}, {end_rel}) exceeds slice length {}",
self.len()
),
));
}
self.stack.zero(self.start() + start, n)
}
#[cfg(feature = "set")]
#[inline]
pub fn fill(&mut self, value: u8) -> io::Result<()> {
self.stack.repeat(self.start(), [value], self.len())
}
#[cfg(feature = "set")]
#[inline]
pub fn fill_with(&mut self, mut f: impl FnMut() -> u8) -> io::Result<()> {
let buf: Vec<u8> = (0..self.len()).map(|_| f()).collect();
self.write(buf)
}
#[cfg(feature = "set")]
#[inline]
pub fn copy_from_slice(&mut self, src: &[u8]) -> io::Result<()> {
assert_eq!(
src.len() as u64,
self.len(),
"copy_from_slice: length mismatch"
);
self.stack.set(self.start(), src)
}
#[cfg(all(feature = "set", feature = "atomic"))]
pub fn copy_from_bstack_slice(&mut self, src: &BStackSlice<'_>) -> io::Result<()> {
assert_eq!(
src.len(),
self.len(),
"copy_from_bstack_slice: length mismatch"
);
if !std::ptr::eq(src.stack(), self.stack) {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"BStackSlice::copy_from_bstack_slice: source belongs to a different BStack",
));
}
if self.is_empty() {
return Ok(());
}
self.stack.copy(src.start(), self.start(), self.len())
}
#[cfg(all(feature = "set", feature = "atomic"))]
pub fn copy_within(&mut self, src_range: Range<u64>, dest: u64) -> io::Result<()> {
assert!(
src_range.start <= src_range.end,
"copy_within: range start must be <= end"
);
assert!(
src_range.end <= self.len(),
"copy_within: range end must be <= slice length"
);
let n = src_range.end - src_range.start;
let dest_end = dest
.checked_add(n)
.expect("copy_within: dest + len overflows u64");
assert!(
dest_end <= self.len(),
"copy_within: dest range exceeds slice length"
);
if n == 0 {
return Ok(());
}
self.stack
.copy(self.start() + src_range.start, self.start() + dest, n)
}
#[cfg(all(feature = "set", feature = "atomic"))]
pub fn swap(&mut self, other: &mut BStackSlice<'_>) -> io::Result<()> {
assert_eq!(self.len(), other.len(), "swap: length mismatch");
if !std::ptr::eq(self.stack, other.stack()) {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"BStackSlice::swap: slices belong to different BStacks",
));
}
if self.is_empty() || self.start() == other.start() {
return Ok(());
}
self.stack
.cross_exchange(self.start(), other.start(), self.len())
}
#[cfg(all(feature = "set", feature = "atomic"))]
#[inline]
pub fn reverse(&mut self) -> io::Result<()> {
self.stack
.process(self.start(), self.end(), |buf| buf.reverse())
}
#[cfg(all(feature = "set", feature = "atomic"))]
pub fn rotate_left(&mut self, mid: u64) -> io::Result<()> {
assert!(
mid <= self.len(),
"rotate_left: mid must be <= slice length"
);
self.stack.process(self.start(), self.end(), |buf| {
buf.rotate_left(mid as usize)
})
}
#[cfg(all(feature = "set", feature = "atomic"))]
pub fn rotate_right(&mut self, k: u64) -> io::Result<()> {
assert!(k <= self.len(), "rotate_right: k must be <= slice length");
self.stack
.process(self.start(), self.end(), |buf| buf.rotate_right(k as usize))
}
#[inline]
pub fn reader(&self) -> BStackSliceReader<'a> {
BStackSliceReader {
slice: self.clone(),
cursor: 0,
}
}
#[inline]
pub fn reader_at(&self, offset: u64) -> BStackSliceReader<'a> {
BStackSliceReader {
slice: self.clone(),
cursor: offset,
}
}
#[cfg(feature = "set")]
#[inline]
pub fn writer(self) -> BStackSliceWriter<'a> {
BStackSliceWriter {
slice: self,
cursor: 0,
}
}
#[cfg(feature = "set")]
#[inline]
pub fn writer_at(self, offset: u64) -> BStackSliceWriter<'a> {
BStackSliceWriter {
slice: self,
cursor: offset,
}
}
}
impl<'a> PartialEq for BStackSlice<'a> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.range == other.range
}
}
impl<'a> Eq for BStackSlice<'a> {}
impl<'a> Hash for BStackSlice<'a> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.range.hash(state);
}
}
impl<'a> PartialOrd for BStackSlice<'a> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<'a> Ord for BStackSlice<'a> {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.range.cmp(&other.range)
}
}
impl<'a> PartialEq<BStackRange> for BStackSlice<'a> {
#[inline]
fn eq(&self, other: &BStackRange) -> bool {
self.range == *other
}
}
impl<'a> PartialEq<BStackSlice<'a>> for BStackRange {
#[inline]
fn eq(&self, other: &BStackSlice<'a>) -> bool {
*self == other.range
}
}
impl<'a> PartialOrd<BStackRange> for BStackSlice<'a> {
#[inline]
fn partial_cmp(&self, other: &BStackRange) -> Option<std::cmp::Ordering> {
Some(self.range.cmp(other))
}
}
impl<'a> PartialOrd<BStackSlice<'a>> for BStackRange {
#[inline]
fn partial_cmp(&self, other: &BStackSlice<'a>) -> Option<std::cmp::Ordering> {
Some(self.cmp(&other.range))
}
}
impl<'a> From<BStackSlice<'a>> for BStackRange {
#[inline]
fn from(s: BStackSlice<'a>) -> BStackRange {
s.range
}
}
impl<'a> From<BStackSlice<'a>> for [u8; 16] {
#[inline]
fn from(s: BStackSlice<'a>) -> Self {
s.range.to_bytes()
}
}
impl<'a> From<BStackSlice<'a>> for BStackSliceReader<'a> {
#[inline]
fn from(slice: BStackSlice<'a>) -> Self {
BStackSliceReader { slice, cursor: 0 }
}
}
#[cfg(feature = "set")]
impl<'a> From<BStackSlice<'a>> for BStackSliceWriter<'a> {
#[inline]
fn from(slice: BStackSlice<'a>) -> Self {
BStackSliceWriter { slice, cursor: 0 }
}
}
pub struct BStackOwnedSlice<'a, A: BStackAllocator> {
allocator: &'a A,
range: BStackRange,
}
impl<'a, A: BStackAllocator> fmt::Debug for BStackOwnedSlice<'a, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BStackOwnedSlice")
.field("start", &self.start())
.field("end", &self.end())
.field("len", &self.len())
.finish_non_exhaustive()
}
}
impl<'a, A: BStackAllocator> BStackOwnedSlice<'a, A> {
#[inline]
pub unsafe fn from_raw_parts(allocator: &'a A, offset: u64, len: u64) -> Self {
Self {
allocator,
range: unsafe { BStackRange::from_raw_parts(offset, len) },
}
}
#[inline]
pub unsafe fn from_raw_range(allocator: &'a A, range: BStackRange) -> Self {
Self { allocator, range }
}
#[inline]
pub fn empty(allocator: &'a A) -> Self {
Self {
allocator,
range: BStackRange::empty(),
}
}
#[inline]
pub fn start(&self) -> u64 {
self.range.start()
}
#[inline]
pub fn end(&self) -> u64 {
self.range.end()
}
#[inline]
pub fn len(&self) -> u64 {
self.range.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.range.is_empty()
}
#[inline]
pub fn range(&self) -> Range<u64> {
self.range.range()
}
#[inline]
pub fn as_range(&self) -> BStackRange {
self.range
}
#[inline]
pub fn to_bytes(&self) -> [u8; 16] {
self.range.to_bytes()
}
#[inline]
pub unsafe fn from_bytes(allocator: &'a A, bytes: [u8; 16]) -> Self {
Self {
allocator,
range: BStackRange::from_bytes(bytes),
}
}
#[inline]
pub fn allocator(&self) -> &'a A {
self.allocator
}
#[inline]
pub fn as_slice<'s>(&'s self) -> BStackSlice<'s> {
BStackSlice {
stack: self.allocator.stack(),
range: self.range,
}
}
#[inline]
pub fn as_slice_mut<'s>(&'s mut self) -> BStackSlice<'s> {
BStackSlice {
stack: self.allocator.stack(),
range: self.range,
}
}
#[inline]
pub fn read(&self) -> io::Result<Vec<u8>> {
self.as_slice().read()
}
#[inline]
pub fn read_into(&self, buf: &mut [u8]) -> io::Result<()> {
self.as_slice().read_into(buf)
}
#[inline]
pub fn read_range(&self, start: u64, end: u64) -> io::Result<Vec<u8>> {
self.as_slice().read_range(start, end)
}
#[inline]
pub fn read_range_into(&self, start: u64, buf: &mut [u8]) -> io::Result<()> {
self.as_slice().read_range_into(start, buf)
}
#[inline]
pub fn head<'s>(&'s self, n: u64) -> BStackSlice<'s> {
self.as_slice().head(n)
}
#[inline]
pub fn tail<'s>(&'s self, n: u64) -> BStackSlice<'s> {
self.as_slice().tail(n)
}
#[inline]
pub fn split_at<'s>(&'s self, mid: u64) -> (BStackSlice<'s>, BStackSlice<'s>) {
self.as_slice().split_at(mid)
}
#[inline]
pub fn split_at_mut<'s>(&'s mut self, mid: u64) -> (BStackSlice<'s>, BStackSlice<'s>) {
let mut view = self.as_slice_mut();
view.split_at_mut(mid)
}
#[inline]
pub fn get(&self, index: u64) -> io::Result<Option<u8>> {
self.as_slice().get(index)
}
#[inline]
pub fn contains(&self, needle: u8) -> io::Result<bool> {
self.as_slice().contains(needle)
}
#[inline]
pub fn starts_with(&self, prefix: &[u8]) -> io::Result<bool> {
self.as_slice().starts_with(prefix)
}
#[inline]
pub fn ends_with(&self, suffix: &[u8]) -> io::Result<bool> {
self.as_slice().ends_with(suffix)
}
#[inline]
pub fn find(&self, needle: u8) -> io::Result<Option<u64>> {
self.as_slice().find(needle)
}
#[inline]
pub fn rfind(&self, needle: u8) -> io::Result<Option<u64>> {
self.as_slice().rfind(needle)
}
#[inline]
pub fn position(&self, predicate: impl Fn(u8) -> bool) -> io::Result<Option<u64>> {
self.as_slice().position(predicate)
}
#[inline]
pub fn rposition(&self, predicate: impl Fn(u8) -> bool) -> io::Result<Option<u64>> {
self.as_slice().rposition(predicate)
}
#[cfg(feature = "set")]
#[inline]
pub fn write(&mut self, data: impl AsRef<[u8]>) -> io::Result<()> {
self.as_slice_mut().write(data)
}
#[cfg(feature = "set")]
#[inline]
pub fn write_range(&mut self, start: u64, data: impl AsRef<[u8]>) -> io::Result<()> {
self.as_slice_mut().write_range(start, data)
}
#[cfg(feature = "set")]
#[inline]
pub fn zero(&mut self) -> io::Result<()> {
self.as_slice_mut().zero()
}
#[cfg(feature = "set")]
#[inline]
pub fn zero_range(&mut self, start: u64, n: u64) -> io::Result<()> {
self.as_slice_mut().zero_range(start, n)
}
#[cfg(feature = "set")]
#[inline]
pub fn fill(&mut self, value: u8) -> io::Result<()> {
self.as_slice_mut().fill(value)
}
#[cfg(feature = "set")]
#[inline]
pub fn fill_with(&mut self, f: impl FnMut() -> u8) -> io::Result<()> {
self.as_slice_mut().fill_with(f)
}
#[cfg(feature = "set")]
#[inline]
pub fn copy_from_slice(&mut self, src: &[u8]) -> io::Result<()> {
self.as_slice_mut().copy_from_slice(src)
}
#[cfg(all(feature = "set", feature = "atomic"))]
#[inline]
pub fn copy_from_bstack_slice(&mut self, src: &BStackSlice<'_>) -> io::Result<()> {
self.as_slice_mut().copy_from_bstack_slice(src)
}
#[cfg(all(feature = "set", feature = "atomic"))]
#[inline]
pub fn copy_within(&mut self, src_range: Range<u64>, dest: u64) -> io::Result<()> {
self.as_slice_mut().copy_within(src_range, dest)
}
#[cfg(all(feature = "set", feature = "atomic"))]
#[inline]
pub fn swap(&mut self, other: &mut BStackSlice<'_>) -> io::Result<()> {
self.as_slice_mut().swap(other)
}
#[cfg(all(feature = "set", feature = "atomic"))]
#[inline]
pub fn reverse(&mut self) -> io::Result<()> {
self.as_slice_mut().reverse()
}
#[cfg(all(feature = "set", feature = "atomic"))]
#[inline]
pub fn rotate_left(&mut self, mid: u64) -> io::Result<()> {
self.as_slice_mut().rotate_left(mid)
}
#[cfg(all(feature = "set", feature = "atomic"))]
#[inline]
pub fn rotate_right(&mut self, k: u64) -> io::Result<()> {
self.as_slice_mut().rotate_right(k)
}
#[inline]
pub fn reader<'s>(&'s self) -> BStackSliceReader<'s> {
self.as_slice().reader()
}
#[inline]
pub fn reader_at<'s>(&'s self, offset: u64) -> BStackSliceReader<'s> {
self.as_slice().reader_at(offset)
}
#[cfg(feature = "set")]
#[inline]
pub fn writer<'s>(&'s mut self) -> BStackSliceWriter<'s> {
self.as_slice_mut().writer()
}
#[cfg(feature = "set")]
#[inline]
pub fn writer_at<'s>(&'s mut self, offset: u64) -> BStackSliceWriter<'s> {
self.as_slice_mut().writer_at(offset)
}
}
impl<'a, A: BStackAllocator> PartialEq for BStackOwnedSlice<'a, A> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.range == other.range
}
}
impl<'a, A: BStackAllocator> Eq for BStackOwnedSlice<'a, A> {}
impl<'a, A: BStackAllocator> Hash for BStackOwnedSlice<'a, A> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.range.hash(state);
}
}
impl<'a, A: BStackAllocator> PartialOrd for BStackOwnedSlice<'a, A> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<'a, A: BStackAllocator> Ord for BStackOwnedSlice<'a, A> {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.range.cmp(&other.range)
}
}
impl<'a, A: BStackAllocator> PartialEq<BStackSlice<'a>> for BStackOwnedSlice<'a, A> {
#[inline]
fn eq(&self, other: &BStackSlice<'a>) -> bool {
self.range == other.range
}
}
impl<'a, A: BStackAllocator> PartialEq<BStackOwnedSlice<'a, A>> for BStackSlice<'a> {
#[inline]
fn eq(&self, other: &BStackOwnedSlice<'a, A>) -> bool {
self.range == other.range
}
}
impl<'a, A: BStackAllocator> PartialEq<BStackRange> for BStackOwnedSlice<'a, A> {
#[inline]
fn eq(&self, other: &BStackRange) -> bool {
self.range == *other
}
}
impl<'a, A: BStackAllocator> PartialEq<BStackOwnedSlice<'a, A>> for BStackRange {
#[inline]
fn eq(&self, other: &BStackOwnedSlice<'a, A>) -> bool {
*self == other.range
}
}
impl<'a, A: BStackAllocator> PartialOrd<BStackSlice<'a>> for BStackOwnedSlice<'a, A> {
#[inline]
fn partial_cmp(&self, other: &BStackSlice<'a>) -> Option<std::cmp::Ordering> {
Some(self.range.cmp(&other.range))
}
}
impl<'a, A: BStackAllocator> PartialOrd<BStackOwnedSlice<'a, A>> for BStackSlice<'a> {
#[inline]
fn partial_cmp(&self, other: &BStackOwnedSlice<'a, A>) -> Option<std::cmp::Ordering> {
Some(self.range.cmp(&other.range))
}
}
impl<'a, A: BStackAllocator> PartialOrd<BStackRange> for BStackOwnedSlice<'a, A> {
#[inline]
fn partial_cmp(&self, other: &BStackRange) -> Option<std::cmp::Ordering> {
Some(self.range.cmp(other))
}
}
impl<'a, A: BStackAllocator> PartialOrd<BStackOwnedSlice<'a, A>> for BStackRange {
#[inline]
fn partial_cmp(&self, other: &BStackOwnedSlice<'a, A>) -> Option<std::cmp::Ordering> {
Some(self.cmp(&other.range))
}
}
impl<'a, A: BStackAllocator> From<BStackOwnedSlice<'a, A>> for BStackRange {
#[inline]
fn from(s: BStackOwnedSlice<'a, A>) -> BStackRange {
s.range
}
}
impl<'a, A: BStackAllocator> From<BStackOwnedSlice<'a, A>> for [u8; 16] {
#[inline]
fn from(s: BStackOwnedSlice<'a, A>) -> Self {
s.range.to_bytes()
}
}
pub struct BStackSliceReader<'a> {
slice: BStackSlice<'a>,
cursor: u64,
}
impl<'a> Clone for BStackSliceReader<'a> {
#[inline]
fn clone(&self) -> Self {
BStackSliceReader {
slice: self.slice.clone(),
cursor: self.cursor,
}
}
}
impl<'a> fmt::Debug for BStackSliceReader<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BStackSliceReader")
.field("start", &self.slice.start())
.field("end", &self.slice.end())
.field("len", &self.slice.len())
.field("cursor", &self.cursor)
.finish_non_exhaustive()
}
}
impl<'a> BStackSliceReader<'a> {
#[inline]
pub fn position(&self) -> u64 {
self.cursor
}
#[inline]
pub fn into_slice(self) -> BStackSlice<'a> {
self.slice
}
#[inline]
pub fn slice(&self) -> &BStackSlice<'a> {
&self.slice
}
}
impl<'a> io::Read for BStackSliceReader<'a> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
if buf.is_empty() || self.cursor >= self.slice.len() {
return Ok(0);
}
let available = (self.slice.len() - self.cursor) as usize;
let n = buf.len().min(available);
let abs_start = self.slice.start() + self.cursor;
self.slice.stack.get_into(abs_start, &mut buf[..n])?;
self.cursor += n as u64;
Ok(n)
}
}
impl<'a> io::Seek for BStackSliceReader<'a> {
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
let len = self.slice.len() as i128;
let new_pos = match pos {
io::SeekFrom::Start(n) => n as i128,
io::SeekFrom::End(n) => len + n as i128,
io::SeekFrom::Current(n) => self.cursor as i128 + n as i128,
};
if new_pos < 0 {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"seek before beginning of slice",
));
}
self.cursor = new_pos as u64;
Ok(self.cursor)
}
}
impl<'a> PartialEq for BStackSliceReader<'a> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.slice == other.slice && self.cursor == other.cursor
}
}
impl<'a> Eq for BStackSliceReader<'a> {}
impl<'a> Hash for BStackSliceReader<'a> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.slice.hash(state);
self.cursor.hash(state);
}
}
impl<'a> PartialOrd for BStackSliceReader<'a> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<'a> Ord for BStackSliceReader<'a> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let self_pos = self.slice.start() + self.cursor;
let other_pos = other.slice.start() + other.cursor;
self_pos
.cmp(&other_pos)
.then(self.slice.len().cmp(&other.slice.len()))
}
}
impl<'a> From<BStackSliceReader<'a>> for BStackSlice<'a> {
#[inline]
fn from(r: BStackSliceReader<'a>) -> Self {
r.into_slice()
}
}
impl<'a> PartialEq<BStackSlice<'a>> for BStackSliceReader<'a> {
#[inline]
fn eq(&self, other: &BStackSlice<'a>) -> bool {
&self.slice == other
}
}
impl<'a> PartialEq<BStackSliceReader<'a>> for BStackSlice<'a> {
#[inline]
fn eq(&self, other: &BStackSliceReader<'a>) -> bool {
self == &other.slice
}
}
impl<'a> PartialOrd<BStackSlice<'a>> for BStackSliceReader<'a> {
#[inline]
fn partial_cmp(&self, other: &BStackSlice<'a>) -> Option<std::cmp::Ordering> {
Some(self.slice.cmp(other))
}
}
impl<'a> PartialOrd<BStackSliceReader<'a>> for BStackSlice<'a> {
#[inline]
fn partial_cmp(&self, other: &BStackSliceReader<'a>) -> Option<std::cmp::Ordering> {
Some(self.cmp(&other.slice))
}
}
#[cfg(feature = "set")]
pub struct BStackSliceWriter<'a> {
slice: BStackSlice<'a>,
cursor: u64,
}
#[cfg(feature = "set")]
impl<'a> fmt::Debug for BStackSliceWriter<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BStackSliceWriter")
.field("start", &self.slice.start())
.field("end", &self.slice.end())
.field("len", &self.slice.len())
.field("cursor", &self.cursor)
.finish_non_exhaustive()
}
}
#[cfg(feature = "set")]
impl<'a> BStackSliceWriter<'a> {
#[inline]
pub fn position(&self) -> u64 {
self.cursor
}
#[inline]
pub fn into_slice(self) -> BStackSlice<'a> {
self.slice
}
#[inline]
pub fn slice(&self) -> &BStackSlice<'a> {
&self.slice
}
}
#[cfg(feature = "set")]
impl<'a> io::Write for BStackSliceWriter<'a> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
if buf.is_empty() || self.cursor >= self.slice.len() {
return Ok(0);
}
let available = (self.slice.len() - self.cursor) as usize;
let n = buf.len().min(available);
let abs_start = self.slice.start() + self.cursor;
self.slice.stack.set(abs_start, &buf[..n])?;
self.cursor += n as u64;
Ok(n)
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
#[cfg(feature = "set")]
impl<'a> io::Seek for BStackSliceWriter<'a> {
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
let len = self.slice.len() as i128;
let new_pos = match pos {
io::SeekFrom::Start(n) => n as i128,
io::SeekFrom::End(n) => len + n as i128,
io::SeekFrom::Current(n) => self.cursor as i128 + n as i128,
};
if new_pos < 0 {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"seek before beginning of slice",
));
}
self.cursor = new_pos as u64;
Ok(self.cursor)
}
}
#[cfg(feature = "set")]
impl<'a> PartialEq for BStackSliceWriter<'a> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.slice == other.slice && self.cursor == other.cursor
}
}
#[cfg(feature = "set")]
impl<'a> Eq for BStackSliceWriter<'a> {}
#[cfg(feature = "set")]
impl<'a> Hash for BStackSliceWriter<'a> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.slice.hash(state);
self.cursor.hash(state);
}
}
#[cfg(feature = "set")]
impl<'a> PartialOrd for BStackSliceWriter<'a> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[cfg(feature = "set")]
impl<'a> Ord for BStackSliceWriter<'a> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let self_pos = self.slice.start() + self.cursor;
let other_pos = other.slice.start() + other.cursor;
self_pos
.cmp(&other_pos)
.then(self.slice.len().cmp(&other.slice.len()))
}
}
#[cfg(feature = "set")]
impl<'a> From<BStackSliceWriter<'a>> for BStackSlice<'a> {
#[inline]
fn from(w: BStackSliceWriter<'a>) -> Self {
w.into_slice()
}
}
#[cfg(feature = "set")]
impl<'a> From<BStackSliceReader<'a>> for BStackSliceWriter<'a> {
#[inline]
fn from(r: BStackSliceReader<'a>) -> Self {
BStackSliceWriter {
slice: r.slice,
cursor: r.cursor,
}
}
}
#[cfg(feature = "set")]
impl<'a> From<BStackSliceWriter<'a>> for BStackSliceReader<'a> {
#[inline]
fn from(w: BStackSliceWriter<'a>) -> Self {
BStackSliceReader {
slice: w.slice,
cursor: w.cursor,
}
}
}
#[cfg(feature = "set")]
impl<'a> PartialEq<BStackSliceWriter<'a>> for BStackSliceReader<'a> {
#[inline]
fn eq(&self, other: &BStackSliceWriter<'a>) -> bool {
self.slice == other.slice && self.cursor == other.cursor
}
}
#[cfg(feature = "set")]
impl<'a> PartialEq<BStackSliceReader<'a>> for BStackSliceWriter<'a> {
#[inline]
fn eq(&self, other: &BStackSliceReader<'a>) -> bool {
self.slice == other.slice && self.cursor == other.cursor
}
}
#[cfg(feature = "set")]
impl<'a> PartialEq<BStackSlice<'a>> for BStackSliceWriter<'a> {
#[inline]
fn eq(&self, other: &BStackSlice<'a>) -> bool {
&self.slice == other
}
}
#[cfg(feature = "set")]
impl<'a> PartialEq<BStackSliceWriter<'a>> for BStackSlice<'a> {
#[inline]
fn eq(&self, other: &BStackSliceWriter<'a>) -> bool {
self == &other.slice
}
}
#[cfg(feature = "set")]
impl<'a> PartialOrd<BStackSlice<'a>> for BStackSliceWriter<'a> {
#[inline]
fn partial_cmp(&self, other: &BStackSlice<'a>) -> Option<std::cmp::Ordering> {
Some(self.slice.cmp(other))
}
}
#[cfg(feature = "set")]
impl<'a> PartialOrd<BStackSliceWriter<'a>> for BStackSliceReader<'a> {
fn partial_cmp(&self, other: &BStackSliceWriter<'a>) -> Option<std::cmp::Ordering> {
let self_pos = self.slice.start() + self.cursor;
let other_pos = other.slice.start() + other.cursor;
Some(
self_pos
.cmp(&other_pos)
.then(self.slice.len().cmp(&other.slice.len())),
)
}
}
#[cfg(feature = "set")]
impl<'a> PartialOrd<BStackSliceReader<'a>> for BStackSliceWriter<'a> {
fn partial_cmp(&self, other: &BStackSliceReader<'a>) -> Option<std::cmp::Ordering> {
let self_pos = self.slice.start() + self.cursor;
let other_pos = other.slice.start() + other.cursor;
Some(
self_pos
.cmp(&other_pos)
.then(self.slice.len().cmp(&other.slice.len())),
)
}
}