use crate::fastcpy::slice_copy;
pub trait Sink {
fn push(&mut self, byte: u8);
fn pos(&self) -> usize;
fn capacity(&self) -> usize;
fn extend_from_slice(&mut self, data: &[u8]);
fn extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize);
fn extend_from_within_overlapping(&mut self, start: usize, num_bytes: usize);
fn output_mut_with_pos(&mut self) -> (&mut [u8], &mut 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 Sink for SliceSink<'_> {
#[inline]
fn push(&mut self, byte: u8) {
self.output[self.pos] = byte;
self.pos += 1;
}
#[inline]
fn pos(&self) -> usize {
self.pos
}
#[inline]
fn capacity(&self) -> usize {
self.output.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_attr(feature = "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;
}
#[inline]
fn output_mut_with_pos(&mut self) -> (&mut [u8], &mut usize) {
(self.output, &mut self.pos)
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_sink_slice() {
use crate::sink::Sink;
use crate::sink::SliceSink;
let mut data = vec![0; 5];
let sink = SliceSink::new(&mut data, 1);
assert_eq!(sink.pos(), 1);
assert_eq!(sink.capacity(), 5);
}
}