1use crate::Error;
2
3const POSIMM_CODE: u8 = 0b00000000;
4const POSIMM_MASK: u8 = 0b01111111;
5const POSIMM_LAST: u8 = POSIMM_CODE + POSIMM_MASK;
6
7const NEGIMM_CODE: u8 = 0b11100000;
8const NEGIMM_MASK: u8 = 0b00011111;
9const NEGIMM_LAST: u8 = NEGIMM_CODE + NEGIMM_MASK;
10
11const STRIMM_CODE: u8 = 0b10000000;
12const STRIMM_MASK: u8 = 0b00011111;
13const STRIMM_LAST: u8 = STRIMM_CODE + STRIMM_MASK;
14
15const ARRIMM_CODE: u8 = 0b10100000;
16const ARRIMM_MASK: u8 = 0b00001111;
17const ARRIMM_LAST: u8 = ARRIMM_CODE + ARRIMM_MASK;
18
19const MAPIMM_CODE: u8 = 0b10110000;
20const MAPIMM_MASK: u8 = 0b00001111;
21const MAPIMM_LAST: u8 = MAPIMM_CODE + MAPIMM_MASK;
22
23const BITS_8: u8 = 0b00;
24const BITS_16: u8 = 0b01;
25const BITS_32: u8 = 0b10;
26const BITS_64: u8 = 0b11;
27
28const FLEX: u8 = 0b11;
29
30const ARRAY_CODE: u8 = 0b11000000;
31const ARRAY_CODE_U8: u8 = ARRAY_CODE + BITS_8;
32const ARRAY_CODE_U16: u8 = ARRAY_CODE + BITS_16;
33const ARRAY_CODE_U32: u8 = ARRAY_CODE + BITS_32;
34const ARRAY_CODE_FLEX: u8 = ARRAY_CODE + FLEX;
35
36const MAP_CODE: u8 = 0b11000100;
37const MAP_CODE_U8: u8 = MAP_CODE + BITS_8;
38const MAP_CODE_U16: u8 = MAP_CODE + BITS_16;
39const MAP_CODE_U32: u8 = MAP_CODE + BITS_32;
40const MAP_CODE_FLEX: u8 = MAP_CODE + FLEX;
41
42const UNSIGNED_CODE: u8 = 0b11001000;
43const UNSIGNED_CODE_U8: u8 = UNSIGNED_CODE + BITS_8;
44const UNSIGNED_CODE_U16: u8 = UNSIGNED_CODE + BITS_16;
45const UNSIGNED_CODE_U32: u8 = UNSIGNED_CODE + BITS_32;
46const UNSIGNED_CODE_U64: u8 = UNSIGNED_CODE + BITS_64;
47
48const SIGNED_CODE: u8 = 0b11001100;
49const SIGNED_CODE_U8: u8 = SIGNED_CODE + BITS_8;
50const SIGNED_CODE_U16: u8 = SIGNED_CODE + BITS_16;
51const SIGNED_CODE_U32: u8 = SIGNED_CODE + BITS_32;
52const SIGNED_CODE_U64: u8 = SIGNED_CODE + BITS_64;
53
54const STR_CODE: u8 = 0b11010000;
55const STR_CODE_U8: u8 = STR_CODE + BITS_8;
56const STR_CODE_U16: u8 = STR_CODE + BITS_16;
57const STR_CODE_U32: u8 = STR_CODE + BITS_32;
58
59const BIN_CODE: u8 = 0b11010100;
60const BIN_CODE_U8: u8 = BIN_CODE + BITS_8;
61const BIN_CODE_U16: u8 = BIN_CODE + BITS_16;
62const BIN_CODE_U32: u8 = BIN_CODE + BITS_32;
63
64const FLOAT_CODE_32: u8 = 0b11011010;
65const FLOAT_CODE_64: u8 = FLOAT_CODE_32 + 1;
66
67const BOOL_CODE_0: u8 = 0b11011100;
68const BOOL_CODE_1: u8 = BOOL_CODE_0 + 1;
69
70const NULL_CODE: u8 = 0b11011110;
71const TERM_CODE: u8 = 0b11011111;
72
73const BOOL_MASK: u8 = 0b00000001;
74
75pub enum Marker {
84 ImmPos {
86 value: u8,
88 },
89
90 ImmNeg {
92 value: i8,
94 },
95
96 ImmStr {
98 len: u8,
100 },
101
102 ImmArr {
104 len: u8,
106 },
107
108 ImmMap {
110 len: u8,
112 },
113
114 A8,
116
117 A16,
119
120 A32,
122
123 AFlex,
126
127 M8,
129
130 M16,
132
133 M32,
135
136 MFlex,
139
140 U8,
142
143 U16,
145
146 U32,
148
149 U64,
151
152 I8,
154
155 I16,
157
158 I32,
160
161 I64,
163
164 S8,
166
167 S16,
169
170 S32,
172
173 B8,
175
176 B16,
178
179 B32,
181
182 F32,
184
185 F64,
187
188 Bool {
190 value: bool,
192 },
193
194 Null,
196
197 Term,
199
200 Reserved,
202}
203
204impl Marker {
205 fn code(&self) -> u8 {
206 match self {
207 Marker::ImmPos { .. } => POSIMM_CODE,
208 Marker::ImmNeg { .. } => NEGIMM_CODE,
209 Marker::ImmStr { .. } => STRIMM_CODE,
210 Marker::ImmArr { .. } => ARRIMM_CODE,
211 Marker::ImmMap { .. } => MAPIMM_CODE,
212
213 Marker::A8 => ARRAY_CODE_U8,
214 Marker::A16 => ARRAY_CODE_U16,
215 Marker::A32 => ARRAY_CODE_U32,
216 Marker::AFlex => ARRAY_CODE_FLEX,
217
218 Marker::M8 => MAP_CODE_U8,
219 Marker::M16 => MAP_CODE_U16,
220 Marker::M32 => MAP_CODE_U32,
221 Marker::MFlex => MAP_CODE_FLEX,
222
223 Marker::U8 => UNSIGNED_CODE_U8,
224 Marker::U16 => UNSIGNED_CODE_U16,
225 Marker::U32 => UNSIGNED_CODE_U32,
226 Marker::U64 => UNSIGNED_CODE_U64,
227
228 Marker::I8 => SIGNED_CODE_U8,
229 Marker::I16 => SIGNED_CODE_U16,
230 Marker::I32 => SIGNED_CODE_U32,
231 Marker::I64 => SIGNED_CODE_U64,
232
233 Marker::S8 => STR_CODE_U8,
234 Marker::S16 => STR_CODE_U16,
235 Marker::S32 => STR_CODE_U32,
236
237 Marker::B8 => BIN_CODE_U8,
238 Marker::B16 => BIN_CODE_U16,
239 Marker::B32 => BIN_CODE_U32,
240
241 Marker::F32 => FLOAT_CODE_32,
242 Marker::F64 => FLOAT_CODE_64,
243
244 Marker::Bool { .. } => BOOL_CODE_0,
245
246 Marker::Null => NULL_CODE,
247 Marker::Term => TERM_CODE,
248
249 Marker::Reserved => panic!(),
250 }
251 }
252
253 fn mask(&self) -> u8 {
254 match self {
255 Marker::ImmPos { .. } => POSIMM_MASK,
256 Marker::ImmNeg { .. } => NEGIMM_MASK,
257 Marker::ImmStr { .. } => STRIMM_MASK,
258 Marker::ImmArr { .. } => ARRIMM_MASK,
259 Marker::ImmMap { .. } => MAPIMM_MASK,
260
261 Marker::Bool { .. } => BOOL_MASK,
262
263 Marker::Reserved => panic!(),
264
265 _ => 0,
266 }
267 }
268
269 pub fn encoding(&self) -> u8 {
271 let code = self.code();
272 let mask = self.mask();
273
274 let imm = match self {
275 Marker::ImmPos { value } => *value,
276 Marker::ImmNeg { value } => *value as u8,
277 Marker::ImmStr { len } | Marker::ImmArr { len } | Marker::ImmMap { len } => *len,
278 Marker::Bool { value } => *value as u8,
279
280 _ => 0,
281 };
282
283 code | (imm & mask)
284 }
285
286 pub fn argument_bytes(&self) -> usize {
291 match self {
292 Marker::A8 | Marker::M8 | Marker::U8 | Marker::I8 | Marker::S8 | Marker::B8 => 1,
293 Marker::A16 | Marker::M16 | Marker::U16 | Marker::I16 | Marker::S16 | Marker::B16 => 2,
294
295 Marker::A32
296 | Marker::M32
297 | Marker::U32
298 | Marker::I32
299 | Marker::S32
300 | Marker::B32
301 | Marker::F32 => 4,
302
303 Marker::U64 | Marker::I64 | Marker::F64 => 8,
304
305 Marker::Reserved => panic!(),
306
307 _ => 0,
308 }
309 }
310
311 pub fn decode(value: u8) -> Result<Self, Error> {
316 let marker = match value {
317 POSIMM_CODE..=POSIMM_LAST => Marker::ImmPos { value },
318 NEGIMM_CODE..=NEGIMM_LAST => Marker::ImmNeg { value: value as i8 },
319 STRIMM_CODE..=STRIMM_LAST => Marker::ImmStr {
320 len: value & STRIMM_MASK,
321 },
322 ARRIMM_CODE..=ARRIMM_LAST => Marker::ImmArr {
323 len: value & ARRIMM_MASK,
324 },
325 MAPIMM_CODE..=MAPIMM_LAST => Marker::ImmMap {
326 len: value & MAPIMM_MASK,
327 },
328
329 ARRAY_CODE_U8 => Marker::A8,
330 ARRAY_CODE_U16 => Marker::A16,
331 ARRAY_CODE_U32 => Marker::A32,
332 ARRAY_CODE_FLEX => Marker::AFlex,
333
334 MAP_CODE_U8 => Marker::M8,
335 MAP_CODE_U16 => Marker::M16,
336 MAP_CODE_U32 => Marker::M32,
337 MAP_CODE_FLEX => Marker::MFlex,
338
339 UNSIGNED_CODE_U8 => Marker::U8,
340 UNSIGNED_CODE_U16 => Marker::U16,
341 UNSIGNED_CODE_U32 => Marker::U32,
342 UNSIGNED_CODE_U64 => Marker::U64,
343
344 SIGNED_CODE_U8 => Marker::I8,
345 SIGNED_CODE_U16 => Marker::I16,
346 SIGNED_CODE_U32 => Marker::I32,
347 SIGNED_CODE_U64 => Marker::I64,
348
349 STR_CODE_U8 => Marker::S8,
350 STR_CODE_U16 => Marker::S16,
351 STR_CODE_U32 => Marker::S32,
352
353 BIN_CODE_U8 => Marker::B8,
354 BIN_CODE_U16 => Marker::B16,
355 BIN_CODE_U32 => Marker::B32,
356
357 FLOAT_CODE_32 => Marker::F32,
358 FLOAT_CODE_64 => Marker::F64,
359
360 BOOL_CODE_0 => Marker::Bool { value: false },
361 BOOL_CODE_1 => Marker::Bool { value: true },
362
363 NULL_CODE => Marker::Null,
364 TERM_CODE => Marker::Term,
365
366 _ => return Err(Error::BadMarker),
367 };
368
369 Ok(marker)
370 }
371
372 pub fn is_str(&self) -> bool {
374 match self {
375 Marker::ImmStr { .. } | Marker::S8 | Marker::S16 | Marker::S32 => true,
376 _ => false,
377 }
378 }
379
380 pub fn is_map(&self) -> bool {
382 match self {
383 Marker::ImmMap { .. } | Marker::M8 | Marker::M16 | Marker::M32 | Marker::MFlex => true,
384 _ => false,
385 }
386 }
387
388 pub fn is_array(&self) -> bool {
390 match self {
391 Marker::ImmArr { .. } | Marker::A8 | Marker::A16 | Marker::A32 | Marker::AFlex => true,
392 _ => false,
393 }
394 }
395}