1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
2#![doc = include_str!("../README.md")]
3#![deny(missing_docs)]
4#![no_std]
5
6use core::convert::TryFrom;
7
8#[derive(Clone, Copy, Debug)]
10pub enum EpeeError {
11 InvalidHeader,
13 Short(usize),
15 UnrecognizedType,
17 ArrayWhenUnit,
19 TrailingBytes(usize),
21 DepthLimitExceeded,
23}
24
25const HEADER: &[u8] = b"\x01\x11\x01\x01\x01\x01\x02\x01\x01";
27
28#[derive(Clone, Copy, PartialEq, Eq, Debug)]
30#[repr(u8)]
31pub enum Type {
32 Int64 = 1,
34 Int32 = 2,
36 Int16 = 3,
38 Int8 = 4,
40 Uint64 = 5,
42 Uint32 = 6,
44 Uint16 = 7,
46 Uint8 = 8,
48 Double = 9,
50 String = 10,
52 Bool = 11,
54 Object = 12,
56 }
58
59#[derive(Clone, Copy, Debug)]
61#[repr(u8)]
62pub enum Array {
63 Unit = 0,
65 Array = 1 << 7,
67}
68
69enum TypeOrEntry {
70 Type(Type),
72 Entry,
74}
75
76impl TypeOrEntry {
77 fn to_u8(self) -> u8 {
78 match self {
79 TypeOrEntry::Type(kind) => kind as u8,
80 TypeOrEntry::Entry => u8::MAX,
81 }
82 }
83
84 fn from_u8(kind: u8) -> Self {
86 match kind {
87 0xff => TypeOrEntry::Entry,
88 _ => TypeOrEntry::Type(
89 Type::read(&mut (&[kind] as &[u8]))
90 .expect("Type we converted to u8 could not be converted back")
91 .0,
92 ),
93 }
94 }
95}
96
97fn read_byte(reader: &mut &[u8]) -> Result<u8, EpeeError> {
98 #[allow(clippy::len_zero)]
99 if reader.len() < 1 {
100 Err(EpeeError::Short(1))?;
101 }
102 let byte = reader[0];
103 *reader = &reader[1 ..];
104 Ok(byte)
105}
106
107fn read_bytes<'a, const N: usize>(reader: &mut &'a [u8]) -> Result<&'a [u8], EpeeError> {
108 if reader.len() < N {
109 Err(EpeeError::Short(N))?;
110 }
111 let res = &reader[.. N];
112 *reader = &reader[N ..];
113 Ok(res)
114}
115
116fn read_varint(reader: &mut &[u8]) -> Result<u64, EpeeError> {
118 let vi_start = read_byte(reader)?;
119 let len = match vi_start & 0b11 {
120 0 => 1,
121 1 => 2,
122 2 => 4,
123 3 => 8,
124 _ => unreachable!(),
125 };
126 let mut vi = u64::from(vi_start >> 2);
127 for i in 1 .. len {
128 vi |= u64::from(read_byte(reader)?) << (((i - 1) * 8) + 6);
129 }
130 Ok(vi)
131}
132
133impl Type {
134 fn read(reader: &mut &[u8]) -> Result<(Self, u64), EpeeError> {
136 let kind = read_byte(reader)?;
137 let array = kind & (Array::Array as u8);
138 let kind = kind & (!(Array::Array as u8));
139
140 let kind = match kind {
141 1 => Type::Int64,
142 2 => Type::Int32,
143 3 => Type::Int16,
144 4 => Type::Int8,
145 5 => Type::Uint64,
146 6 => Type::Uint32,
147 7 => Type::Uint16,
148 8 => Type::Uint8,
149 9 => Type::Double,
150 10 => Type::String,
151 11 => Type::Bool,
152 12 => Type::Object,
153 _ => Err(EpeeError::UnrecognizedType)?,
154 };
155
156 let len = if array != 0 { read_varint(reader)? } else { 1 };
157
158 Ok((kind, len))
159 }
160}
161
162fn read_key<'a>(reader: &mut &'a [u8]) -> Result<&'a [u8], EpeeError> {
164 let len = usize::from(read_byte(reader)?);
165 if reader.len() < len {
166 Err(EpeeError::Short(len))?;
167 }
168 let res = &reader[.. len];
169 *reader = &reader[len ..];
170 Ok(res)
171}
172
173const EPEE_LIB_MAX_OBJECT_DEPTH: usize = 100;
176const MAX_OBJECT_DEPTH: usize = EPEE_LIB_MAX_OBJECT_DEPTH + 3;
179
180#[repr(C, packed)]
181struct PackedTypes([u8; MAX_OBJECT_DEPTH]);
182
183struct Stack {
193 remaining: [u64; MAX_OBJECT_DEPTH],
194 types: PackedTypes,
195 len: usize,
196}
197#[cfg(test)]
198const _ASSERT_KIBIBYTE_STACK: [(); 1024 - core::mem::size_of::<Stack>()] =
199 [(); 1024 - core::mem::size_of::<Stack>()];
200
201impl Stack {
202 fn new(initial_item: (TypeOrEntry, u64)) -> Self {
203 let (kind, amount) = initial_item;
204 Self {
205 types: PackedTypes([kind.to_u8(); MAX_OBJECT_DEPTH]),
206 remaining: [amount; MAX_OBJECT_DEPTH],
207 len: 1,
208 }
209 }
210
211 fn len(&self) -> usize {
212 self.len
213 }
214
215 fn last(&mut self) -> (TypeOrEntry, &mut u64) {
217 let i = self.len - 1;
218 let kind = TypeOrEntry::from_u8(self.types.0[i]);
219 let amount = &mut self.remaining[i];
220 (kind, amount)
221 }
222
223 fn push(&mut self, kind: TypeOrEntry, amount: u64) -> Result<(), EpeeError> {
224 if self.len == MAX_OBJECT_DEPTH {
225 Err(EpeeError::DepthLimitExceeded)?;
226 }
227 self.types.0[self.len] = kind.to_u8();
228 self.remaining[self.len] = amount;
229 self.len += 1;
230 Ok(())
231 }
232
233 fn pop(&mut self) {
235 self.len -= 1;
236 }
237}
238
239struct Seek<'a> {
241 reader: &'a [u8],
242 kind: Type,
243 array: Array,
244 field_name: &'static str,
245 stack: Stack,
246}
247#[cfg(test)]
248const _ASSERT_KIBIBYTE_SEEK: [(); 1024 - core::mem::size_of::<Seek>()] =
249 [(); 1024 - core::mem::size_of::<Seek>()];
250
251impl<'a> Seek<'a> {
252 fn new(
253 mut reader: &'a [u8],
254 kind: Type,
255 array: Array,
256 field_name: &'static str,
257 ) -> Result<Self, EpeeError> {
258 if read_bytes::<{ HEADER.len() }>(&mut reader).ok() != Some(HEADER) {
259 Err(EpeeError::InvalidHeader)?;
260 }
261 let stack = Stack::new((TypeOrEntry::Type(Type::Object), 1u64));
262 Ok(Seek { reader, kind, array, field_name, stack })
263 }
264}
265
266impl<'a> Iterator for Seek<'a> {
267 type Item = Result<(u64, &'a [u8]), EpeeError>;
268 fn next(&mut self) -> Option<Self::Item> {
269 (|| -> Result<_, EpeeError> {
270 let mut result = None;
271
272 while self.stack.len() > 0 {
273 let (kind, remaining) = self.stack.last();
274
275 *remaining -= 1;
277 if *remaining == 0 {
278 self.stack.pop();
279 }
280
281 match kind {
282 TypeOrEntry::Type(Type::Int64) => {
283 read_bytes::<{ core::mem::size_of::<i64>() }>(&mut self.reader)?;
284 }
285 TypeOrEntry::Type(Type::Int32) => {
286 read_bytes::<{ core::mem::size_of::<i32>() }>(&mut self.reader)?;
287 }
288 TypeOrEntry::Type(Type::Int16) => {
289 read_bytes::<{ core::mem::size_of::<i16>() }>(&mut self.reader)?;
290 }
291 TypeOrEntry::Type(Type::Int8) => {
292 read_bytes::<{ core::mem::size_of::<i8>() }>(&mut self.reader)?;
293 }
294 TypeOrEntry::Type(Type::Uint64) => {
295 read_bytes::<{ core::mem::size_of::<u64>() }>(&mut self.reader)?;
296 }
297 TypeOrEntry::Type(Type::Uint32) => {
298 read_bytes::<{ core::mem::size_of::<u32>() }>(&mut self.reader)?;
299 }
300 TypeOrEntry::Type(Type::Uint16) => {
301 read_bytes::<{ core::mem::size_of::<u16>() }>(&mut self.reader)?;
302 }
303 TypeOrEntry::Type(Type::Uint8) => {
304 read_bytes::<{ core::mem::size_of::<u8>() }>(&mut self.reader)?;
305 }
306 TypeOrEntry::Type(Type::Double) => {
307 read_bytes::<{ core::mem::size_of::<f64>() }>(&mut self.reader)?;
308 }
309 TypeOrEntry::Type(Type::String) => {
310 let len = usize::try_from(read_varint(&mut self.reader)?)
311 .map_err(|_| EpeeError::Short(usize::MAX))?;
312 if self.reader.len() < len {
313 Err(EpeeError::Short(len))?;
314 }
315 self.reader = &self.reader[len ..];
316 }
317 TypeOrEntry::Type(Type::Bool) => {
318 read_bytes::<{ core::mem::size_of::<bool>() }>(&mut self.reader)?;
319 }
320 TypeOrEntry::Type(Type::Object) => {
321 let amount_of_entries = read_varint(&mut self.reader)?;
322 self.stack.push(TypeOrEntry::Entry, amount_of_entries)?;
323 }
324 TypeOrEntry::Entry => {
325 let key = read_key(&mut self.reader)?;
326 let (kind, len) = Type::read(&mut self.reader)?;
327 let result_stack_depth = self.stack.len();
328 self.stack.push(TypeOrEntry::Type(kind), len)?;
329 if (key == self.field_name.as_bytes()) && (kind == self.kind) {
331 if matches!(self.array, Array::Unit) && (len != 1) {
334 Err(EpeeError::ArrayWhenUnit)?;
335 }
336 result = Some(((len, self.reader), result_stack_depth));
337 }
338 }
339 }
340
341 if let Some(((epee_len, bytes), stack_depth)) = result {
342 if stack_depth == self.stack.len() {
343 let remaining_bytes = self.reader.len();
344 let bytes_used_by_field = bytes.len() - remaining_bytes;
345 return Ok(Some((epee_len, &bytes[.. bytes_used_by_field])));
346 }
347 }
348 }
349
350 if !self.reader.is_empty() {
351 Err(EpeeError::TrailingBytes(self.reader.len()))?;
352 }
353
354 Ok(None)
355 })()
356 .transpose()
357 }
358}
359
360pub fn seek_all<'a>(
365 reader: &'a [u8],
366 kind: Type,
367 array: Array,
368 field_name: &'static str,
369) -> Result<impl Iterator<Item = Result<(u64, &'a [u8]), EpeeError>>, EpeeError> {
370 Seek::new(reader, kind, array, field_name)
371}