hacspec_lib/
buf.rs

1//! # hacspec buffer
2//!
3//! A buffer for operating on hacspec bytes.
4
5#[cfg(all(feature = "alloc", not(feature = "std")))]
6extern crate alloc;
7#[cfg(feature = "std")]
8extern crate std as alloc;
9
10use alloc::collections::VecDeque;
11
12use super::seq::*;
13use crate::prelude::*;
14
15#[derive(Debug, Clone)]
16pub struct ByteBuffer {
17    value: VecDeque<Bytes>,
18}
19
20impl ByteBuffer {
21    /// Create an empty buffer.
22    #[cfg_attr(feature = "use_attributes", in_hacspec)]
23    pub fn new() -> ByteBuffer {
24        Self {
25            value: VecDeque::new(),
26        }
27    }
28
29    /// Create a buffer from [`Bytes`].
30    #[cfg_attr(feature = "use_attributes", in_hacspec)]
31    pub fn from_seq(seq: Bytes) -> ByteBuffer {
32        let mut value: VecDeque<Bytes> = VecDeque::with_capacity(1);
33        value.push_back(seq);
34        Self { value }
35    }
36
37    /// Add a new chunk of [`Bytes`] to this [`ByteBuffer`].
38    #[cfg_attr(feature = "use_attributes", unsafe_hacspec)]
39    pub fn concat_owned(mut self, seq: Bytes) -> ByteBuffer {
40        self.value.push_back(seq);
41        self
42    }
43
44    /// Split off `num` bytes and return the [`Bytes`].
45    #[cfg_attr(feature = "use_attributes", unsafe_hacspec)]
46    pub fn split_off(mut self, len: usize) -> (Bytes, ByteBuffer) {
47        assert!(self.value.len() != 0, "The buffer is empty.");
48
49        if len == self.value[0].len() {
50            // This is the efficient case.
51            let val = self.value.pop_front().unwrap();
52            (val, self)
53        } else {
54            // Here we don't optimize and just take the first len bytes.
55            let mut out = self.value.pop_front().unwrap();
56            assert!(out.len() != len);
57            if out.len() > len {
58                let (full_out, to_keep) = out.split_off(len);
59                out = full_out;
60                self.value.push_front(to_keep);
61                return (out, self);
62            } else {
63                assert!(out.len() < len);
64                // Get more bytes until we have enough.
65                while out.len() < len {
66                    let next = self.value.pop_front().unwrap();
67                    if next.len() <= (len - out.len()) {
68                        out = out.concat_owned(next);
69                    } else {
70                        let (next, to_keep) = next.split_off(len - out.len());
71                        out = out.concat_owned(next);
72                        self.value.push_front(to_keep);
73                    }
74                }
75                return (out, self);
76            }
77        }
78    }
79
80    /// Get the buffer a single [`Bytes`] object (not efficient).
81    #[cfg_attr(feature = "use_attributes", unsafe_hacspec)]
82    pub fn to_bytes(&self) -> Bytes {
83        let mut out = Bytes::new(0);
84        for value in self.value.iter() {
85            out = out.concat_owned(value.clone());
86        }
87        out
88    }
89
90    /// Get the buffer a single [`Bytes`] object (efficient, consuming the buffer).
91    #[cfg_attr(feature = "use_attributes", unsafe_hacspec)]
92    pub fn into_bytes(mut self) -> Bytes {
93        self.value
94            .drain(..)
95            .fold(Bytes::new(0), |acc, next| acc.concat_owned(next))
96    }
97}
98
99// === Helper functions not in hacspec === //
100
101impl ByteBuffer {}