kvstructs/
header.rs

1use crate::{binary_put_uvariant_to_bufmut, binary_put_uvariant_to_vec, binary_uvarint};
2use alloc::vec::Vec;
3use bytes::{BufMut, Bytes, BytesMut};
4
5/// Maximum possible size of the header. The maximum size of header struct will be 18 but the
6/// maximum size of variant encoded header will be 21.
7pub const MAX_HEADER_SIZE: usize = 21;
8
9/// Header is used in value log as a header before Entry.
10#[derive(Copy, Clone, Eq, PartialEq, Debug)]
11#[repr(C)]
12pub struct Header {
13    meta: u8,
14    user_meta: u8,
15    k_len: u32,
16    v_len: u32,
17    expires_at: u64,
18}
19
20impl Header {
21    /// Encodes the header into `Vec<u8>`. The provided `Vec<u8>` should be at least 5 bytes. The
22    /// function will panic if out `Vec<u8>` isn't large enough to hold all the values.
23    /// The encoded header looks like
24    /// +------+----------+------------+--------------+-----------+
25    ///
26    /// | Meta | UserMeta | Key Length | Value Length | ExpiresAt |
27    ///
28    /// +------+----------+------------+--------------+-----------+
29    pub fn encode(&self) -> (usize, Vec<u8>) {
30        let mut buf = Vec::with_capacity(MAX_HEADER_SIZE);
31        buf.push(self.meta);
32        buf.push(self.user_meta);
33        let mut index = 2;
34
35        index += binary_put_uvariant_to_vec(&mut buf, self.k_len as u64);
36        index += binary_put_uvariant_to_vec(&mut buf, self.v_len as u64);
37        index += binary_put_uvariant_to_vec(&mut buf, self.expires_at);
38        (index, buf)
39    }
40
41    /// Encodes the header into `Bytes`. The provided `Bytes` should be at least 5 bytes. The
42    /// function will panic if out `Bytes` isn't large enough to hold all the values.
43    /// The encoded header looks like
44    ///
45    /// +------+----------+------------+--------------+-----------+
46    ///
47    /// | Meta | UserMeta | Key Length | Value Length | ExpiresAt |
48    ///
49    /// +------+----------+------------+--------------+-----------+
50    pub fn encode_to_bytes(&self) -> (usize, Bytes) {
51        let mut buf = BytesMut::with_capacity(MAX_HEADER_SIZE);
52        buf.put_u8(self.meta);
53        buf.put_u8(self.user_meta);
54        let mut index = 2;
55
56        index += binary_put_uvariant_to_bufmut(&mut buf, self.k_len as u64);
57        index += binary_put_uvariant_to_bufmut(&mut buf, self.v_len as u64);
58        index += binary_put_uvariant_to_bufmut(&mut buf, self.expires_at);
59        (index, buf.freeze())
60    }
61
62    /// Decode Header from byte slice, returns Header and number of bytes read
63    pub fn decode(data: &[u8]) -> (usize, Self) {
64        let mut index = 2;
65        let (k_len, ctr) = binary_uvarint(&data[index..]);
66        index += ctr;
67
68        let (v_len, ctr) = binary_uvarint(&data[index..]);
69        index += ctr;
70
71        let (expires_at, ctr) = binary_uvarint(&data[index..]);
72        (
73            index + ctr,
74            Self {
75                k_len: k_len as u32,
76                v_len: v_len as u32,
77                expires_at,
78                meta: data[0],
79                user_meta: data[1],
80            },
81        )
82    }
83
84    /// Decode Header from Cursor<>, returns Header and number of bytes read
85    #[cfg(feature = "std")]
86    pub fn decode_reader(
87        reader: &mut impl ByteReader,
88        hash_buf: &mut BytesMut,
89    ) -> std::io::Result<(usize, Self)> {
90        use crate::binary_read_and_put_uvarint;
91
92        let start = reader.position();
93        let meta = reader.read_byte()?;
94        hash_buf.put_u8(meta);
95        let user_meta = reader.read_byte()?;
96        hash_buf.put_u8(user_meta);
97
98        let k_len = binary_read_and_put_uvarint(reader, hash_buf)?;
99        let v_len = binary_read_and_put_uvarint(reader, hash_buf)?;
100        let expires_at = binary_read_and_put_uvarint(reader, hash_buf)?;
101        let h_len = reader.position() - start;
102        let h = Header {
103            k_len: k_len as u32,
104            v_len: v_len as u32,
105            expires_at,
106            meta,
107            user_meta,
108        };
109
110        Ok((h_len as usize, h))
111    }
112
113    /// update the data of the header according to the provided byte slice.
114    /// Returns the number of bytes read.
115    pub fn update(&mut self, data: &[u8]) -> usize {
116        self.meta = data[0];
117        self.user_meta = data[1];
118        let mut index = 2;
119
120        let (k_len, ctr) = binary_uvarint(&data[index..]);
121        self.k_len = k_len as u32;
122        index += ctr;
123
124        let (v_len, ctr) = binary_uvarint(&data[index..]);
125        self.v_len = v_len as u32;
126        index += ctr;
127
128        let (expires_at, ctr) = binary_uvarint(&data[index..]);
129        self.expires_at = expires_at;
130        index + ctr
131    }
132
133    /// Get the value length
134    #[inline]
135    pub fn get_value_len(&self) -> u32 {
136        self.v_len
137    }
138
139    /// Set the value length
140    #[inline]
141    pub fn set_value_len(&mut self, vlen: u32) {
142        self.v_len = vlen
143    }
144
145    /// Get the key length
146    #[inline]
147    pub fn get_key_len(&self) -> u32 {
148        self.k_len
149    }
150
151    /// Set the key length
152    #[inline]
153    pub fn set_key_len(&mut self, klen: u32) {
154        self.k_len = klen
155    }
156
157    /// Get the meta
158    #[inline]
159    pub fn get_meta(&self) -> u8 {
160        self.meta
161    }
162
163    /// Set the meta
164    #[inline]
165    pub fn set_meta(&mut self, meta: u8) {
166        self.meta = meta
167    }
168
169    /// Get the user meta
170    #[inline]
171    pub fn get_user_meta(&self) -> u8 {
172        self.user_meta
173    }
174
175    /// Set the user meta
176    #[inline]
177    pub fn set_user_meta(&mut self, user_meta: u8) {
178        self.meta = user_meta
179    }
180
181    /// Get the expires_at
182    #[inline]
183    pub fn get_expires_at(&self) -> u64 {
184        self.expires_at
185    }
186
187    /// Set the expires_at
188    #[inline]
189    pub fn set_expires_at(&mut self, expires_at: u64) {
190        self.expires_at = expires_at
191    }
192}
193
194cfg_std! {
195    use std::io::Read;
196
197    ///
198    pub trait ByteReader {
199        /// Read one byte and advance the current position
200        fn read_byte(&mut self) -> std::io::Result<u8>;
201        /// Returns the current position
202        fn position(&self) -> u64;
203    }
204
205    macro_rules! impl_byte_reader_for_cursor {
206        ($($ty: ty),+ $(,)?) => {
207            $(
208                impl ByteReader for std::io::Cursor<$ty> {
209                    #[inline]
210                    fn read_byte(&mut self) -> std::io::Result<u8> {
211                        let mut buf = [0; 1];
212                        self.read_exact(&mut buf).map(|_| buf[0])
213                    }
214
215                    #[inline]
216                    fn position(&self) -> u64 {
217                        self.position()
218                    }
219                }
220            )*
221        };
222    }
223
224    impl_byte_reader_for_cursor! {
225        Box<[u8]>,
226        &[u8],
227        &mut [u8],
228        Vec<u8>,
229        &Vec<u8>,
230        &mut Vec<u8>
231    }
232}