1#[derive(Debug, Default)]
6pub(crate) struct Tail<const MAX: usize> {
7 buf: Vec<u8>,
8}
9
10impl<const MAX: usize> Tail<MAX> {
11 pub(crate) fn push(&mut self, data: &[u8]) {
13 let data = &data[data.len().saturating_sub(MAX)..];
15 if self.buf.len() + data.len() > 2 * MAX {
17 self.buf.drain(..self.buf.len() - (MAX - data.len()));
18 }
19 self.buf.extend_from_slice(data);
20 }
21
22 pub(crate) fn end(&self) -> &[u8] {
24 &self.buf[self.buf.len().saturating_sub(MAX)..]
25 }
26
27 pub(crate) fn into_end(mut self) -> Vec<u8> {
29 let excess = self.buf.len().saturating_sub(MAX);
30 self.buf.drain(..excess);
31 self.buf
32 }
33}
34
35#[cfg(test)]
36mod tests {
37 use super::*;
38
39 #[test]
40 fn keeps_the_end() {
41 let mut tail = Tail::<4>::default();
42 tail.push(b"ab");
43 assert_eq!(tail.end(), b"ab");
44 for i in 0..100u8 {
45 tail.push(&[i]);
46 assert!(tail.buf.len() <= 8);
47 }
48 assert_eq!(tail.end(), [96, 97, 98, 99]);
49
50 tail.push(&(0..100).collect::<Vec<u8>>());
52 assert!(tail.buf.capacity() <= 8);
53 assert_eq!(tail.end(), [96, 97, 98, 99]);
54 tail.push(&[1, 2]);
55 assert_eq!(tail.end(), [98, 99, 1, 2]);
56 assert_eq!(tail.into_end(), [98, 99, 1, 2]);
57 }
58}