1use core::marker::PhantomData;
2
3use crate::{EpeeError, Stack, io::*};
4
5#[derive(Clone, Copy, PartialEq, Eq, Debug)]
7pub enum Type {
8 Int64 = 1,
10 Int32 = 2,
12 Int16 = 3,
14 Int8 = 4,
16 Uint64 = 5,
18 Uint32 = 6,
20 Uint16 = 7,
22 Uint8 = 8,
24 Double = 9,
26 String = 10,
28 Bool = 11,
30 Object = 12,
32 }
38
39#[derive(Clone, Copy, Debug)]
41#[repr(u8)]
42pub enum Array {
43 Unit = 0,
45 Array = 1 << 7,
47}
48
49#[derive(Clone, Copy, PartialEq, Eq)]
55pub(crate) enum TypeOrEntry {
56 Type(Type),
58 Entry,
60}
61
62impl Type {
63 pub fn read<'encoding>(reader: &mut impl BytesLike<'encoding>) -> Result<(Self, u64), EpeeError> {
65 let kind = reader.read_byte()?;
66
67 #[expect(clippy::as_conversions)]
69 let array = kind & (Array::Array as u8);
70 #[expect(clippy::as_conversions)]
72 let kind = kind & (!(Array::Array as u8));
73
74 let kind = match kind {
75 1 => Type::Int64,
76 2 => Type::Int32,
77 3 => Type::Int16,
78 4 => Type::Int8,
79 5 => Type::Uint64,
80 6 => Type::Uint32,
81 7 => Type::Uint16,
82 8 => Type::Uint8,
83 9 => Type::Double,
84 10 => Type::String,
85 11 => Type::Bool,
86 12 => Type::Object,
87 _ => Err(EpeeError::UnrecognizedType)?,
88 };
89
90 let len = if array != 0 { read_varint(reader)? } else { 1 };
96
97 Ok((kind, len))
98 }
99}
100
101fn read_key<'encoding, B: BytesLike<'encoding>>(
105 reader: &mut B,
106) -> Result<String<'encoding, B>, EpeeError> {
107 let len = usize::from(reader.read_byte()?);
108 if len == 0 {
109 Err(EpeeError::EmptyKey)?;
110 }
111 let (len, bytes) = reader.read_bytes(len)?;
112 Ok(String { len, bytes, _encoding: PhantomData })
113}
114
115pub(crate) enum SingleStepResult<'encoding, B: BytesLike<'encoding>> {
117 Object { fields: usize },
118 Entry { key: String<'encoding, B>, kind: Type, len: usize },
119 Unit,
120}
121
122impl Stack {
123 pub(crate) fn single_step<'encoding, B: BytesLike<'encoding>>(
128 &mut self,
129 encoding: &mut B,
130 ) -> Result<Option<SingleStepResult<'encoding, B>>, EpeeError> {
131 let Some(kind) = self.pop() else {
132 return Ok(None);
133 };
134 match kind {
135 TypeOrEntry::Type(Type::Int64) => {
136 encoding.advance::<{ core::mem::size_of::<i64>() }>()?;
137 }
138 TypeOrEntry::Type(Type::Int32) => {
139 encoding.advance::<{ core::mem::size_of::<i32>() }>()?;
140 }
141 TypeOrEntry::Type(Type::Int16) => {
142 encoding.advance::<{ core::mem::size_of::<i16>() }>()?;
143 }
144 TypeOrEntry::Type(Type::Int8) => {
145 encoding.advance::<{ core::mem::size_of::<i8>() }>()?;
146 }
147 TypeOrEntry::Type(Type::Uint64) => {
148 encoding.advance::<{ core::mem::size_of::<u64>() }>()?;
149 }
150 TypeOrEntry::Type(Type::Uint32) => {
151 encoding.advance::<{ core::mem::size_of::<u32>() }>()?;
152 }
153 TypeOrEntry::Type(Type::Uint16) => {
154 encoding.advance::<{ core::mem::size_of::<u16>() }>()?;
155 }
156 TypeOrEntry::Type(Type::Uint8) => {
157 encoding.advance::<{ core::mem::size_of::<u8>() }>()?;
158 }
159 TypeOrEntry::Type(Type::Double) => {
160 encoding.advance::<{ core::mem::size_of::<f64>() }>()?;
161 }
162 TypeOrEntry::Type(Type::String) => {
163 read_str(encoding)?;
164 }
165 TypeOrEntry::Type(Type::Bool) => {
166 encoding.advance::<{ core::mem::size_of::<bool>() }>()?;
167 }
168 TypeOrEntry::Type(Type::Object) => {
169 let fields = read_varint(encoding)?;
170 let fields = usize::try_from(fields).map_err(|_| EpeeError::Short(usize::MAX))?;
173 self.push(TypeOrEntry::Entry, fields)?;
174 return Ok(Some(SingleStepResult::Object { fields }));
175 }
176 TypeOrEntry::Entry => {
177 let key = read_key(encoding)?;
178 let (kind, len) = Type::read(encoding)?;
179 let len = usize::try_from(len).map_err(|_| EpeeError::Short(usize::MAX))?;
180 self.push(TypeOrEntry::Type(kind), len)?;
181 return Ok(Some(SingleStepResult::Entry { key, kind, len }));
182 }
183 }
184 Ok(Some(SingleStepResult::Unit))
185 }
186
187 pub(crate) fn step<'encoding, B: BytesLike<'encoding>>(
191 &mut self,
192 encoding: &mut B,
193 ) -> Result<Option<()>, EpeeError> {
194 let Some((_kind, len)) = self.peek() else { return Ok(None) };
195
196 let current_stack_depth = self.depth();
197 let stop_at_stack_depth = if len.get() > 1 {
199 current_stack_depth
200 } else {
201 current_stack_depth - 1
204 };
205
206 while {
207 self.single_step(encoding)?;
208 self.depth() != stop_at_stack_depth
209 } {}
210
211 Ok(Some(()))
212 }
213}