#[allow(unused_imports)]
use alloc::vec::Vec;
use crate::fastcpy::slice_copy;
#[inline]
#[cfg(feature = "frame")]
pub fn vec_sink_for_compression(
vec: &mut Vec<u8>,
offset: usize,
pos: usize,
required_capacity: usize,
) -> SliceSink {
{
vec.resize(offset + required_capacity, 0);
SliceSink::new(&mut vec[offset..], pos)
}
}
#[cfg(feature = "frame")]
#[inline]
pub fn vec_sink_for_decompression(
vec: &mut Vec<u8>,
offset: usize,
pos: usize,
required_capacity: usize,
) -> SliceSink {
{
vec.resize(offset + required_capacity, 0);
SliceSink::new(&mut vec[offset..], pos)
}
}
pub trait Sink {
#[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
unsafe fn pos_mut_ptr(&mut self) -> *mut u8;
#[allow(dead_code)]
fn byte_at(&mut self, pos: usize) -> u8;
#[cfg(feature = "safe-encode")]
fn push(&mut self, byte: u8);
#[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
unsafe fn base_mut_ptr(&mut self) -> *mut u8;
fn pos(&self) -> usize;
fn capacity(&self) -> usize;
#[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
unsafe fn set_pos(&mut self, new_pos: usize);
#[cfg(feature = "safe-decode")]
fn extend_with_fill(&mut self, byte: u8, len: usize);
fn extend_from_slice(&mut self, data: &[u8]);
fn extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize);
#[cfg(feature = "safe-decode")]
fn extend_from_within(&mut self, start: usize, wild_len: usize, copy_len: usize);
#[cfg(feature = "safe-decode")]
fn extend_from_within_overlapping(&mut self, start: usize, num_bytes: usize);
}
pub struct SliceSink<'a> {
output: &'a mut [u8],
pos: usize,
}
impl<'a> SliceSink<'a> {
#[inline]
pub fn new(output: &'a mut [u8], pos: usize) -> Self {
let _ = &mut output[..pos]; SliceSink { output, pos }
}
}
impl<'a> Sink for SliceSink<'a> {
#[inline]
#[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
unsafe fn pos_mut_ptr(&mut self) -> *mut u8 {
self.base_mut_ptr().add(self.pos()) as *mut u8
}
#[inline]
fn byte_at(&mut self, pos: usize) -> u8 {
self.output[pos]
}
#[inline]
#[cfg(feature = "safe-encode")]
fn push(&mut self, byte: u8) {
self.output[self.pos] = byte;
self.pos += 1;
}
#[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
unsafe fn base_mut_ptr(&mut self) -> *mut u8 {
self.output.as_mut_ptr()
}
#[inline]
fn pos(&self) -> usize {
self.pos
}
#[inline]
fn capacity(&self) -> usize {
self.output.len()
}
#[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
#[inline]
unsafe fn set_pos(&mut self, new_pos: usize) {
debug_assert!(new_pos <= self.capacity());
self.pos = new_pos;
}
#[inline]
#[cfg(feature = "safe-decode")]
fn extend_with_fill(&mut self, byte: u8, len: usize) {
self.output[self.pos..self.pos + len].fill(byte);
self.pos += len;
}
#[inline]
fn extend_from_slice(&mut self, data: &[u8]) {
self.extend_from_slice_wild(data, data.len())
}
#[inline]
fn extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize) {
assert!(copy_len <= data.len());
slice_copy(data, &mut self.output[self.pos..(self.pos) + data.len()]);
self.pos += copy_len;
}
#[inline]
#[cfg(feature = "safe-decode")]
fn extend_from_within(&mut self, start: usize, wild_len: usize, copy_len: usize) {
self.output.copy_within(start..start + wild_len, self.pos);
self.pos += copy_len;
}
#[inline]
#[cfg(feature = "safe-decode")]
#[cfg_attr(nightly, optimize(size))] fn extend_from_within_overlapping(&mut self, start: usize, num_bytes: usize) {
let offset = self.pos - start;
for i in start + offset..start + offset + num_bytes {
self.output[i] = self.output[i - offset];
}
self.pos += num_bytes;
}
}
#[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
pub struct PtrSink {
output: *mut u8,
pos: usize,
cap: usize,
}
#[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
impl PtrSink {
#[inline]
pub fn from_vec(output: &mut Vec<u8>, pos: usize) -> Self {
Self {
output: output.as_mut_ptr(),
pos,
cap: output.capacity(),
}
}
}
#[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
impl Sink for PtrSink {
#[inline]
#[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
unsafe fn pos_mut_ptr(&mut self) -> *mut u8 {
self.base_mut_ptr().add(self.pos()) as *mut u8
}
#[inline]
fn byte_at(&mut self, pos: usize) -> u8 {
unsafe { self.output.add(pos).read() }
}
#[inline]
#[cfg(feature = "safe-encode")]
fn push(&mut self, byte: u8) {
unsafe {
self.pos_mut_ptr().write(byte);
}
self.pos += 1;
}
#[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
unsafe fn base_mut_ptr(&mut self) -> *mut u8 {
self.output
}
#[inline]
fn pos(&self) -> usize {
self.pos
}
#[inline]
fn capacity(&self) -> usize {
self.cap
}
#[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
#[inline]
unsafe fn set_pos(&mut self, new_pos: usize) {
debug_assert!(new_pos <= self.capacity());
self.pos = new_pos;
}
#[inline]
#[cfg(feature = "safe-decode")]
fn extend_with_fill(&mut self, _byte: u8, _len: usize) {
unreachable!();
}
#[inline]
fn extend_from_slice(&mut self, data: &[u8]) {
self.extend_from_slice_wild(data, data.len())
}
#[inline]
fn extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize) {
assert!(copy_len <= data.len());
unsafe {
core::ptr::copy_nonoverlapping(data.as_ptr(), self.pos_mut_ptr(), copy_len);
}
self.pos += copy_len;
}
#[inline]
#[cfg(feature = "safe-decode")]
fn extend_from_within(&mut self, _start: usize, _wild_len: usize, _copy_len: usize) {
unreachable!();
}
#[inline]
#[cfg(feature = "safe-decode")]
fn extend_from_within_overlapping(&mut self, _start: usize, _num_bytes: usize) {
unreachable!();
}
}
#[cfg(test)]
mod tests {
#[test]
#[cfg(any(feature = "safe-encode", feature = "safe-decode"))]
fn test_sink_slice() {
use crate::sink::Sink;
use crate::sink::SliceSink;
use alloc::vec::Vec;
let mut data = Vec::new();
data.resize(5, 0);
let sink = SliceSink::new(&mut data, 1);
assert_eq!(sink.pos(), 1);
assert_eq!(sink.capacity(), 5);
}
}