|
11 | 11 | //! For implementing these newtypes, we provide the [`encoder_newtype`] macro. |
12 | 12 | //! |
13 | 13 |
|
| 14 | +use internals::array_vec::ArrayVec; |
| 15 | +use internals::compact_size; |
| 16 | + |
14 | 17 | use super::Encoder; |
15 | 18 |
|
| 19 | +/// The maximum length of a compact size encoding. |
| 20 | +const SIZE: usize = compact_size::MAX_ENCODING_SIZE; |
| 21 | + |
16 | 22 | /// An encoder for a single byte slice. |
17 | 23 | pub struct BytesEncoder<'sl> { |
18 | 24 | sl: Option<&'sl [u8]>, |
| 25 | + compact_size: Option<ArrayVec<u8, SIZE>>, |
19 | 26 | } |
20 | 27 |
|
21 | 28 | impl<'sl> BytesEncoder<'sl> { |
22 | 29 | /// Constructs a byte encoder which encodes the given byte slice, with no length prefix. |
23 | | - pub fn without_length_prefix(sl: &'sl [u8]) -> Self { Self { sl: Some(sl) } } |
| 30 | + pub fn without_length_prefix(sl: &'sl [u8]) -> Self { |
| 31 | + Self { sl: Some(sl), compact_size: None } |
| 32 | + } |
| 33 | + |
| 34 | + /// Constructs a byte encoder which encodes the given byte slice, with the length prefix. |
| 35 | + pub fn with_length_prefix(sl: &'sl [u8]) -> Self { |
| 36 | + Self { sl: Some(sl), compact_size: Some(compact_size::encode(sl.len())) } |
| 37 | + } |
24 | 38 | } |
25 | 39 |
|
26 | 40 | impl<'e, 'sl> Encoder<'e> for BytesEncoder<'sl> { |
27 | | - fn current_chunk(&self) -> Option<&[u8]> { self.sl } |
| 41 | + fn current_chunk(&self) -> Option<&[u8]> { |
| 42 | + if let Some(compact_size) = self.compact_size.as_ref() { |
| 43 | + Some(compact_size) |
| 44 | + } else { |
| 45 | + self.sl |
| 46 | + } |
| 47 | + } |
28 | 48 |
|
29 | 49 | fn advance(&mut self) -> bool { |
30 | | - self.sl = None; |
31 | | - false |
| 50 | + if self.compact_size.is_some() { |
| 51 | + self.compact_size = None; |
| 52 | + true |
| 53 | + } else { |
| 54 | + self.sl = None; |
| 55 | + false |
| 56 | + } |
32 | 57 | } |
33 | 58 | } |
34 | 59 |
|
@@ -155,3 +180,63 @@ impl< |
155 | 180 | fn current_chunk(&self) -> Option<&[u8]> { self.inner.current_chunk() } |
156 | 181 | fn advance(&mut self) -> bool { self.inner.advance() } |
157 | 182 | } |
| 183 | + |
| 184 | +#[cfg(test)] |
| 185 | +#[cfg(feature = "alloc")] |
| 186 | +mod tests { |
| 187 | + use alloc::vec::Vec; |
| 188 | + |
| 189 | + use super::*; |
| 190 | + |
| 191 | + // Run the encoder i.e., use it to encode into a vector. |
| 192 | + fn run_encoder<'e>(mut encoder: impl Encoder<'e>) -> Vec<u8> { |
| 193 | + let mut vec = Vec::new(); |
| 194 | + while let Some(chunk) = encoder.current_chunk() { |
| 195 | + vec.extend_from_slice(chunk); |
| 196 | + encoder.advance(); |
| 197 | + } |
| 198 | + vec |
| 199 | + } |
| 200 | + |
| 201 | + #[test] |
| 202 | + fn encode_byte_slice_without_prefix() { |
| 203 | + let obj = [1u8, 2, 3]; |
| 204 | + |
| 205 | + let encoder = BytesEncoder::without_length_prefix(&obj); |
| 206 | + let got = run_encoder(encoder); |
| 207 | + |
| 208 | + assert_eq!(got, obj); |
| 209 | + } |
| 210 | + |
| 211 | + #[test] |
| 212 | + fn encode_empty_byte_slice_without_prefix() { |
| 213 | + let obj = []; |
| 214 | + |
| 215 | + let encoder = BytesEncoder::without_length_prefix(&obj); |
| 216 | + let got = run_encoder(encoder); |
| 217 | + |
| 218 | + assert_eq!(got, obj); |
| 219 | + } |
| 220 | + |
| 221 | + #[test] |
| 222 | + fn encode_byte_slice_with_prefix() { |
| 223 | + let obj = [1u8, 2, 3]; |
| 224 | + |
| 225 | + let encoder = BytesEncoder::with_length_prefix(&obj); |
| 226 | + let got = run_encoder(encoder); |
| 227 | + |
| 228 | + let want = [3u8, 1, 2, 3]; |
| 229 | + assert_eq!(got, want); |
| 230 | + } |
| 231 | + |
| 232 | + #[test] |
| 233 | + fn encode_empty_byte_slice_with_prefix() { |
| 234 | + let obj = []; |
| 235 | + |
| 236 | + let encoder = BytesEncoder::with_length_prefix(&obj); |
| 237 | + let got = run_encoder(encoder); |
| 238 | + |
| 239 | + let want = [0u8]; |
| 240 | + assert_eq!(got, want); |
| 241 | + } |
| 242 | +} |
0 commit comments