nautilus_serialization/sbe/
primitives.rs1use std::str;
19
20use super::{MAX_GROUP_SIZE, SbeDecodeError};
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub struct GroupSizeEncoding {
25 pub block_length: u16,
27 pub num_in_group: u32,
29}
30
31impl GroupSizeEncoding {
32 pub const ENCODED_LENGTH: usize = 6;
34
35 pub fn decode(buf: &[u8]) -> Result<Self, SbeDecodeError> {
42 if buf.len() < Self::ENCODED_LENGTH {
43 return Err(SbeDecodeError::BufferTooShort {
44 expected: Self::ENCODED_LENGTH,
45 actual: buf.len(),
46 });
47 }
48
49 let num_in_group = u32::from_le_bytes([buf[2], buf[3], buf[4], buf[5]]);
50 if num_in_group > MAX_GROUP_SIZE {
51 return Err(SbeDecodeError::GroupSizeTooLarge {
52 count: num_in_group,
53 max: MAX_GROUP_SIZE,
54 });
55 }
56
57 Ok(Self {
58 block_length: u16::from_le_bytes([buf[0], buf[1]]),
59 num_in_group,
60 })
61 }
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub struct GroupSize16Encoding {
67 pub block_length: u16,
69 pub num_in_group: u16,
71}
72
73impl GroupSize16Encoding {
74 pub const ENCODED_LENGTH: usize = 4;
76
77 pub fn decode(buf: &[u8]) -> Result<Self, SbeDecodeError> {
84 if buf.len() < Self::ENCODED_LENGTH {
85 return Err(SbeDecodeError::BufferTooShort {
86 expected: Self::ENCODED_LENGTH,
87 actual: buf.len(),
88 });
89 }
90
91 let num_in_group = u16::from_le_bytes([buf[2], buf[3]]);
92 if u32::from(num_in_group) > MAX_GROUP_SIZE {
93 return Err(SbeDecodeError::GroupSizeTooLarge {
94 count: u32::from(num_in_group),
95 max: MAX_GROUP_SIZE,
96 });
97 }
98
99 Ok(Self {
100 block_length: u16::from_le_bytes([buf[0], buf[1]]),
101 num_in_group,
102 })
103 }
104}
105
106pub fn decode_var_string8(buf: &[u8]) -> Result<(&str, usize), SbeDecodeError> {
115 if buf.is_empty() {
116 return Err(SbeDecodeError::BufferTooShort {
117 expected: 1,
118 actual: 0,
119 });
120 }
121
122 let len = usize::from(buf[0]);
123 let total_len = 1 + len;
124 if buf.len() < total_len {
125 return Err(SbeDecodeError::BufferTooShort {
126 expected: total_len,
127 actual: buf.len(),
128 });
129 }
130
131 let s = str::from_utf8(&buf[1..total_len]).map_err(|_| SbeDecodeError::InvalidUtf8)?;
132 Ok((s, total_len))
133}
134
135#[cfg(test)]
136mod tests {
137 use rstest::rstest;
138
139 use super::*;
140
141 #[rstest]
142 fn test_group_size_decode_too_short() {
143 let err = GroupSizeEncoding::decode(&[0, 0, 0]).unwrap_err();
144 assert!(matches!(err, SbeDecodeError::BufferTooShort { .. }));
145 }
146
147 #[rstest]
148 fn test_group_size_decode_too_large() {
149 let mut buf = [0u8; GroupSizeEncoding::ENCODED_LENGTH];
150 buf[2..6].copy_from_slice(&(MAX_GROUP_SIZE + 1).to_le_bytes());
151 let err = GroupSizeEncoding::decode(&buf).unwrap_err();
152 assert!(matches!(err, SbeDecodeError::GroupSizeTooLarge { .. }));
153 }
154
155 #[rstest]
156 fn test_group_size_16_decode_too_large() {
157 let mut buf = [0u8; GroupSize16Encoding::ENCODED_LENGTH];
158 buf[2..4].copy_from_slice(&(MAX_GROUP_SIZE as u16 + 1).to_le_bytes());
159 let err = GroupSize16Encoding::decode(&buf).unwrap_err();
160 assert!(matches!(err, SbeDecodeError::GroupSizeTooLarge { .. }));
161 }
162
163 #[rstest]
164 fn test_decode_var_string8_valid() {
165 let buf = [5u8, b'H', b'E', b'L', b'L', b'O'];
166 let (s, consumed) = decode_var_string8(&buf).unwrap();
167 assert_eq!(s, "HELLO");
168 assert_eq!(consumed, 6);
169 }
170
171 #[rstest]
172 fn test_decode_var_string8_invalid_utf8() {
173 let buf = [2u8, 0xFF, 0xFF];
174 let err = decode_var_string8(&buf).unwrap_err();
175 assert_eq!(err, SbeDecodeError::InvalidUtf8);
176 }
177}