1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![doc = include_str!("../README.md")]
3#![expect(single_use_lifetimes, clippy::elidable_lifetime_names)] #![no_std]
5
6use core::marker::PhantomData;
7
8mod io;
9mod stack;
10mod parser;
11
12pub(crate) use io::*;
13pub use io::{BytesLike, String};
14pub(crate) use stack::*;
15pub use parser::*;
16
17#[derive(Clone, Copy, Debug)]
19pub enum EpeeError {
20 InternalError,
22 InvalidHeader,
24 InvalidVersion(Option<u8>),
28 Short(usize),
30 UnrecognizedType,
32 EmptyKey,
34 DepthLimitExceeded,
36 TypeError,
38 EpeeReuse,
40}
41
42pub const HEADER: [u8; 8] = *b"\x01\x11\x01\x01\x01\x01\x02\x01";
46pub const VERSION: u8 = 1;
50
51pub struct Epee<'encoding, B: BytesLike<'encoding>> {
53 current_encoding_state: B,
54 stack: Stack,
55 error: Option<EpeeError>,
56 _encoding_lifetime: PhantomData<&'encoding ()>,
57}
58pub struct EpeeEntry<'encoding, 'parent, B: BytesLike<'encoding>> {
60 root: Option<&'parent mut Epee<'encoding, B>>,
61 kind: Type,
62 len: usize,
63}
64
65impl<'encoding, 'parent, B: BytesLike<'encoding>> Drop for EpeeEntry<'encoding, 'parent, B> {
67 #[inline(always)]
68 fn drop(&mut self) {
69 if let Some(root) = self.root.take() {
70 while root.error.is_none() && (self.len != 0) {
71 root.error = root.stack.step(&mut root.current_encoding_state).err();
72 self.len -= 1;
73 }
74 }
75 }
76}
77
78impl<'encoding, B: BytesLike<'encoding>> Epee<'encoding, B> {
79 pub fn new(mut encoding: B) -> Result<Self, EpeeError> {
81 {
83 let mut present_header = [0; HEADER.len()];
84 encoding.read_into_slice(&mut present_header)?;
85 if present_header != HEADER {
86 Err(EpeeError::InvalidHeader)?;
87 }
88 }
89
90 {
92 let version = encoding.read_byte().ok();
93 if version != Some(VERSION) {
94 Err(EpeeError::InvalidVersion(version))?;
95 }
96 }
97
98 Ok(Epee {
99 current_encoding_state: encoding,
100 stack: Stack::root_object(),
101 error: None,
102 _encoding_lifetime: PhantomData,
103 })
104 }
105
106 pub fn entry(&mut self) -> Result<EpeeEntry<'encoding, '_, B>, EpeeError> {
112 if (self.stack.depth() != 1) || self.error.is_some() {
113 Err(EpeeError::EpeeReuse)?;
114 }
115 Ok(EpeeEntry { root: Some(self), kind: Type::Object, len: 1 })
116 }
117}
118
119pub struct FieldIterator<'encoding, 'parent, B: BytesLike<'encoding>> {
121 root: &'parent mut Epee<'encoding, B>,
122 len: usize,
123}
124
125impl<'encoding, 'parent, B: BytesLike<'encoding>> Drop for FieldIterator<'encoding, 'parent, B> {
127 #[inline(always)]
128 fn drop(&mut self) {
129 while self.root.error.is_none() && (self.len != 0) {
130 self.root.error = self.root.stack.step(&mut self.root.current_encoding_state).err();
131 self.len -= 1;
132 }
133 }
134}
135
136impl<'encoding, 'parent, B: BytesLike<'encoding>> FieldIterator<'encoding, 'parent, B> {
137 #[expect(clippy::type_complexity, clippy::should_implement_trait)]
149 pub fn next(
150 &mut self,
151 ) -> Option<Result<(String<'encoding, B>, EpeeEntry<'encoding, '_, B>), EpeeError>> {
152 if let Some(error) = self.root.error {
153 return Some(Err(error));
154 }
155
156 self.len = self.len.checked_sub(1)?;
157 let (key, kind, len) = match self.root.stack.single_step(&mut self.root.current_encoding_state)
158 {
159 Ok(Some(SingleStepResult::Entry { key, kind, len })) => (key, kind, len),
160 Ok(_) => return Some(Err(EpeeError::InternalError)),
162 Err(e) => return Some(Err(e)),
163 };
164
165 Some(Ok((key, EpeeEntry { root: Some(self.root), kind, len })))
166 }
167}
168
169pub struct ArrayIterator<'encoding, 'parent, B: BytesLike<'encoding>> {
171 root: &'parent mut Epee<'encoding, B>,
172 kind: Type,
173 len: usize,
174}
175
176impl<'encoding, 'parent, B: BytesLike<'encoding>> Drop for ArrayIterator<'encoding, 'parent, B> {
178 #[inline(always)]
179 fn drop(&mut self) {
180 while self.root.error.is_none() && (self.len != 0) {
181 self.root.error = self.root.stack.step(&mut self.root.current_encoding_state).err();
182 self.len -= 1;
183 }
184 }
185}
186
187impl<'encoding, 'parent, B: BytesLike<'encoding>> ArrayIterator<'encoding, 'parent, B> {
188 #[expect(clippy::should_implement_trait)]
200 pub fn next(&mut self) -> Option<Result<EpeeEntry<'encoding, '_, B>, EpeeError>> {
201 if let Some(err) = self.root.error {
202 return Some(Err(err));
203 }
204
205 self.len = self.len.checked_sub(1)?;
206 Some(Ok(EpeeEntry { root: Some(self.root), kind: self.kind, len: 1 }))
207 }
208}
209
210impl<'encoding, 'parent, B: BytesLike<'encoding>> EpeeEntry<'encoding, 'parent, B> {
211 #[inline(always)]
213 pub fn kind(&self) -> Type {
214 self.kind
215 }
216
217 #[expect(clippy::len_without_is_empty)]
219 #[inline(always)]
220 pub fn len(&self) -> usize {
221 self.len
222 }
223
224 pub fn fields(mut self) -> Result<FieldIterator<'encoding, 'parent, B>, EpeeError> {
226 let root = self.root.take().ok_or(EpeeError::InternalError)?;
227
228 if let Some(err) = root.error {
229 Err(err)?;
230 }
231
232 if (self.kind != Type::Object) || (self.len != 1) {
233 Err(EpeeError::TypeError)?;
234 }
235
236 let len = match root.stack.single_step(&mut root.current_encoding_state)? {
238 Some(SingleStepResult::Object { fields }) => fields,
239 _ => Err(EpeeError::InternalError)?,
240 };
241 Ok(FieldIterator { root, len })
242 }
243
244 pub fn iterate(mut self) -> Result<ArrayIterator<'encoding, 'parent, B>, EpeeError> {
250 let root = self.root.take().ok_or(EpeeError::InternalError)?;
251
252 if let Some(err) = root.error {
253 Err(err)?;
254 }
255
256 Ok(ArrayIterator { root, kind: self.kind, len: self.len })
257 }
258
259 #[expect(clippy::wrong_self_convention)]
260 #[inline(always)]
261 fn to_primitive(mut self, kind: Type, slice: &mut [u8]) -> Result<&mut [u8], EpeeError> {
262 if (self.kind != kind) || (self.len != 1) {
263 Err(EpeeError::TypeError)?;
264 }
265
266 let root = self.root.take().ok_or(EpeeError::InternalError)?;
267 if let Some(error) = root.error {
268 Err(error)?;
269 }
270 root.stack.pop();
271 root.current_encoding_state.read_into_slice(slice)?;
272 Ok(slice)
273 }
274
275 #[inline(always)]
277 pub fn to_i64(self) -> Result<i64, EpeeError> {
278 let mut buf = [0; core::mem::size_of::<i64>()];
279 Ok(i64::from_le_bytes(self.to_primitive(Type::Int64, &mut buf)?.try_into().unwrap()))
280 }
281
282 #[inline(always)]
284 pub fn to_i32(self) -> Result<i32, EpeeError> {
285 let mut buf = [0; core::mem::size_of::<i32>()];
286 Ok(i32::from_le_bytes(self.to_primitive(Type::Int32, &mut buf)?.try_into().unwrap()))
287 }
288
289 #[inline(always)]
291 pub fn to_i16(self) -> Result<i16, EpeeError> {
292 let mut buf = [0; core::mem::size_of::<i16>()];
293 Ok(i16::from_le_bytes(self.to_primitive(Type::Int16, &mut buf)?.try_into().unwrap()))
294 }
295
296 #[inline(always)]
298 pub fn to_i8(self) -> Result<i8, EpeeError> {
299 let mut buf = [0; core::mem::size_of::<i8>()];
300 Ok(i8::from_le_bytes(self.to_primitive(Type::Int8, &mut buf)?.try_into().unwrap()))
301 }
302
303 #[inline(always)]
305 pub fn to_u64(self) -> Result<u64, EpeeError> {
306 let mut buf = [0; core::mem::size_of::<u64>()];
307 Ok(u64::from_le_bytes(self.to_primitive(Type::Uint64, &mut buf)?.try_into().unwrap()))
308 }
309
310 #[inline(always)]
312 pub fn to_u32(self) -> Result<u32, EpeeError> {
313 let mut buf = [0; core::mem::size_of::<u32>()];
314 Ok(u32::from_le_bytes(self.to_primitive(Type::Uint32, &mut buf)?.try_into().unwrap()))
315 }
316
317 #[inline(always)]
319 pub fn to_u16(self) -> Result<u16, EpeeError> {
320 let mut buf = [0; core::mem::size_of::<u16>()];
321 Ok(u16::from_le_bytes(self.to_primitive(Type::Uint16, &mut buf)?.try_into().unwrap()))
322 }
323
324 #[inline(always)]
326 pub fn to_u8(self) -> Result<u8, EpeeError> {
327 let mut buf = [0; core::mem::size_of::<u8>()];
328 Ok(self.to_primitive(Type::Uint8, &mut buf)?[0])
329 }
330
331 #[inline(always)]
333 pub fn to_f64(self) -> Result<f64, EpeeError> {
334 let mut buf = [0; core::mem::size_of::<f64>()];
335 Ok(f64::from_le_bytes(self.to_primitive(Type::Double, &mut buf)?.try_into().unwrap()))
336 }
337
338 #[inline(always)]
340 pub fn to_str(mut self) -> Result<String<'encoding, B>, EpeeError> {
341 if (self.kind != Type::String) || (self.len != 1) {
342 Err(EpeeError::TypeError)?;
343 }
344
345 let root = self.root.take().ok_or(EpeeError::InternalError)?;
346 if let Some(error) = root.error {
347 Err(error)?;
348 }
349 root.stack.pop();
350 read_str(&mut root.current_encoding_state)
351 }
352
353 #[inline(always)]
357 pub fn to_fixed_len_str(self, len: usize) -> Result<String<'encoding, B>, EpeeError> {
358 let str = self.to_str()?;
359 if str.len() != len {
360 Err(EpeeError::TypeError)?;
361 }
362 Ok(str)
363 }
364
365 #[inline(always)]
367 pub fn to_bool(self) -> Result<bool, EpeeError> {
368 let mut buf = [0; core::mem::size_of::<bool>()];
369 Ok(self.to_primitive(Type::Bool, &mut buf)?[0] != 0)
370 }
371}