1use crate::io::{DecodingError, WireType};
2use enc::DecodeFromReadPrefix;
3use enc::var_int::VarIntSize;
4use std::io::{Error, Read};
5
6macro_rules! decode_fixed {
7 ($name:ident, $size:expr, $wire:literal) => {
8 #[doc = concat!("Decodes a `", $wire, "` value from the `Read` prefix given the `first` byte.")]
9 pub fn $name<R>(r: &mut R, first: u8) -> Result<[u8; $size], Error>
10 where
11 R: Read,
12 {
13 let mut buffer: [u8; $size] = [0u8; $size];
14 buffer[0] = first;
15 r.read_exact(&mut buffer[1..])?;
16 Ok(buffer)
17 }
18 };
19}
20
21impl WireType {
22 decode_fixed!(decode_fixed_2_byte, 2, "Fixed2Byte");
25 decode_fixed!(decode_fixed_4_byte, 4, "Fixed4Byte");
26 decode_fixed!(decode_fixed_8_byte, 8, "Fixed8Byte");
27 decode_fixed!(decode_fixed_16_byte, 16, "Fixed16Byte");
28
29 pub fn decode_length_prefixed_bytes<R>(r: &mut R, first: u8) -> Result<Vec<u8>, DecodingError>
31 where
32 R: Read,
33 {
34 let prefix: usize = VarIntSize::decode_from_read_prefix_with_first_byte(r, first)
35 .map_err(DecodingError::from_length_prefix_error)?
36 .value();
37 let mut result: Vec<u8> = Vec::with_capacity(prefix);
38 let read: usize = r.take(prefix as u64).read_to_end(&mut result)?;
39 if read != prefix {
40 return Err(std::io::Error::new(
41 std::io::ErrorKind::UnexpectedEof,
42 "short read for length-prefixed bytes",
43 )
44 .into());
45 }
46 Ok(result)
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use crate::io::WireType;
53 use std::io::{Cursor, Error};
54
55 #[test]
56 fn decode_fixed_2_byte() -> Result<(), Error> {
57 let mut source: Cursor<Vec<u8>> = Cursor::new(vec![1, 2]);
58
59 let result: [u8; 2] = WireType::decode_fixed_2_byte(&mut source, 0)?;
60 assert_eq!(result, [0, 1]);
61
62 Ok(())
63 }
64
65 #[test]
66 fn decode_fixed_4_byte() -> Result<(), Error> {
67 let mut source: Cursor<Vec<u8>> = Cursor::new(vec![1, 2, 3, 4]);
68
69 let result: [u8; 4] = WireType::decode_fixed_4_byte(&mut source, 0)?;
70 assert_eq!(result, [0, 1, 2, 3]);
71
72 Ok(())
73 }
74
75 #[test]
76 fn decode_fixed_8_byte() -> Result<(), Error> {
77 let mut source: Cursor<Vec<u8>> = Cursor::new(vec![1, 2, 3, 4, 5, 6, 7, 8]);
78
79 let result: [u8; 8] = WireType::decode_fixed_8_byte(&mut source, 0)?;
80 assert_eq!(result, [0, 1, 2, 3, 4, 5, 6, 7]);
81
82 Ok(())
83 }
84
85 #[test]
86 fn decode_fixed_16_byte() -> Result<(), Error> {
87 let mut source: Cursor<Vec<u8>> =
88 Cursor::new(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
89
90 let result: [u8; 16] = WireType::decode_fixed_16_byte(&mut source, 0)?;
91 assert_eq!(
92 result,
93 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
94 );
95
96 Ok(())
97 }
98
99 #[test]
100 #[allow(clippy::type_complexity)]
101 fn decode_length_prefixed_bytes() {
102 let mut large_rest: Vec<u8> = vec![0x01];
105 large_rest.extend(std::iter::repeat_n(0xAB, 200));
106 let large_expected: Vec<u8> = vec![0xAB; 200];
107
108 let cases: &[(u8, &[u8], Option<&[u8]>)] = &[
110 (0, &[], Some(&[])),
112 (3, &[1, 2, 3], Some(&[1, 2, 3])),
114 (3, &[1, 2, 3, 99], Some(&[1, 2, 3])),
116 (0xC8, large_rest.as_slice(), Some(large_expected.as_slice())),
119 (5, &[1, 2, 3], None),
121 ];
122
123 for (first, rest, expected) in cases {
124 let mut source: Cursor<&[u8]> = Cursor::new(*rest);
125 let result = WireType::decode_length_prefixed_bytes(&mut source, *first);
126 match (result, expected) {
127 (Ok(bytes), Some(exp)) => {
128 assert_eq!(
129 bytes.as_slice(),
130 *exp,
131 "first={first:#x} rest_len={}",
132 rest.len()
133 );
134 }
135 (Err(_), None) => {}
136 (Ok(bytes), None) => panic!(
137 "first={first:#x} rest_len={}: expected error, got Ok({} bytes)",
138 rest.len(),
139 bytes.len()
140 ),
141 (Err(e), Some(_)) => panic!(
142 "first={first:#x} rest_len={}: expected Ok, got error: {e:?}",
143 rest.len()
144 ),
145 }
146 }
147 }
148}