1use crate::fastcpy::slice_copy;
2
3pub trait Sink {
5 fn push(&mut self, byte: u8);
7
8 fn pos(&self) -> usize;
10
11 fn capacity(&self) -> usize;
13
14 fn extend_from_slice(&mut self, data: &[u8]);
16
17 fn extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize);
20
21 fn extend_from_within_overlapping(&mut self, start: usize, num_bytes: usize);
24
25 fn output_mut_with_pos(&mut self) -> (&mut [u8], &mut usize);
27}
28
29pub struct SliceSink<'a> {
37 output: &'a mut [u8],
38 pos: usize,
39}
40
41impl<'a> SliceSink<'a> {
42 #[inline]
47 pub fn new(output: &'a mut [u8], pos: usize) -> Self {
48 let _ = &mut output[..pos]; SliceSink { output, pos }
50 }
51}
52
53impl Sink for SliceSink<'_> {
54 #[inline]
55 fn push(&mut self, byte: u8) {
56 self.output[self.pos] = byte;
57 self.pos += 1;
58 }
59
60 #[inline]
61 fn pos(&self) -> usize {
62 self.pos
63 }
64
65 #[inline]
66 fn capacity(&self) -> usize {
67 self.output.len()
68 }
69
70 #[inline]
71 fn extend_from_slice(&mut self, data: &[u8]) {
72 self.extend_from_slice_wild(data, data.len());
73 }
74
75 #[inline]
76 fn extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize) {
77 assert!(copy_len <= data.len());
78 slice_copy(data, &mut self.output[self.pos..(self.pos) + data.len()]);
79 self.pos += copy_len;
80 }
81
82 #[inline]
83 #[cfg_attr(feature = "nightly", optimize(size))]
84 fn extend_from_within_overlapping(&mut self, start: usize, num_bytes: usize) {
85 let offset = self.pos - start;
86 if offset == 1 {
87 let val = self.output[start];
88 self.output[self.pos..self.pos + num_bytes].fill(val);
89 } else {
90 let initial = offset.min(num_bytes);
96 self.output.copy_within(start..start + initial, self.pos);
97 let mut copied = initial;
98 while copied < num_bytes {
99 let n = copied.min(num_bytes - copied);
100 let src = self.pos;
101 self.output.copy_within(src..src + n, src + copied);
102 copied += n;
103 }
104 }
105 self.pos += num_bytes;
106 }
107
108 #[inline]
109 fn output_mut_with_pos(&mut self) -> (&mut [u8], &mut usize) {
110 (self.output, &mut self.pos)
111 }
112}
113
114#[cfg(test)]
115mod tests {
116
117 #[test]
118 fn test_sink_slice() {
119 use crate::sink::Sink;
120 use crate::sink::SliceSink;
121 let mut data = vec![0; 5];
122 let sink = SliceSink::new(&mut data, 1);
123 assert_eq!(sink.pos(), 1);
124 assert_eq!(sink.capacity(), 5);
125 }
126}