1extern crate alloc;
63
64use alloc::string::String;
65use alloc::vec;
66use alloc::vec::Vec;
67
68use crate::error::{Error, Result};
69
70pub const ERR_CODEC: i32 = 20;
72
73pub const ERR_CODEC_EOF: i32 = 21;
75
76pub const ERR_CODEC_UTF8: i32 = 22;
78
79pub trait Codec32: Sized {
106 fn encode_32(&self) -> [u8; 32];
108
109 fn decode_32(bytes: &[u8; 32]) -> Result<Self>;
111}
112
113pub trait BytesCodec: Sized {
140 fn encode_bytes(&self) -> Vec<u8>;
142
143 fn decode_bytes(bytes: &[u8]) -> Result<Self>;
145}
146
147#[derive(Clone, Debug, Default)]
164pub struct Encoder {
165 bytes: Vec<u8>,
166}
167
168impl Encoder {
169 pub fn new() -> Self {
171 Self { bytes: Vec::new() }
172 }
173
174 pub fn with_capacity(capacity: usize) -> Self {
178 Self {
179 bytes: Vec::with_capacity(capacity),
180 }
181 }
182
183 pub fn push_u8(&mut self, value: u8) {
185 self.bytes.push(value);
186 }
187
188 pub fn push_u16(&mut self, value: u16) {
190 self.bytes.extend_from_slice(&value.to_le_bytes());
191 }
192
193 pub fn push_u32(&mut self, value: u32) {
195 self.bytes.extend_from_slice(&value.to_le_bytes());
196 }
197
198 pub fn push_u64(&mut self, value: u64) {
200 self.bytes.extend_from_slice(&value.to_le_bytes());
201 }
202
203 pub fn push_u128(&mut self, value: u128) {
205 self.bytes.extend_from_slice(&value.to_le_bytes());
206 }
207
208 pub fn push_bool(&mut self, value: bool) {
210 self.push_u8(if value { 1 } else { 0 });
211 }
212
213 pub fn push_raw(&mut self, bytes: &[u8]) {
215 self.bytes.extend_from_slice(bytes);
216 }
217
218 pub fn push_bytes(&mut self, bytes: &[u8]) {
222 self.push_u32(bytes.len() as u32);
223 self.push_raw(bytes);
224 }
225
226 pub fn push_string(&mut self, value: &str) {
230 self.push_bytes(value.as_bytes());
231 }
232
233 pub fn push_codec<T: BytesCodec>(&mut self, value: &T) {
235 self.push_bytes(&value.encode_bytes());
236 }
237
238 pub fn as_slice(&self) -> &[u8] {
240 &self.bytes
241 }
242
243 pub fn into_vec(self) -> Vec<u8> {
245 self.bytes
246 }
247}
248
249pub struct Decoder<'a> {
264 bytes: &'a [u8],
265 cursor: usize,
266}
267
268impl<'a> Decoder<'a> {
269 pub fn new(bytes: &'a [u8]) -> Self {
271 Self { bytes, cursor: 0 }
272 }
273
274 pub fn remaining(&self) -> usize {
276 self.bytes.len().saturating_sub(self.cursor)
277 }
278
279 fn read_exact(&mut self, len: usize) -> Result<&'a [u8]> {
283 let end = self
284 .cursor
285 .checked_add(len)
286 .ok_or_else(|| Error::new(ERR_CODEC_EOF))?;
287 if end > self.bytes.len() {
288 return Err(Error::new(ERR_CODEC_EOF));
289 }
290 let out = &self.bytes[self.cursor..end];
291 self.cursor = end;
292 Ok(out)
293 }
294
295 pub fn read_array<const N: usize>(&mut self) -> Result<[u8; N]> {
297 let bytes = self.read_exact(N)?;
298 let mut out = [0u8; N];
299 out.copy_from_slice(bytes);
300 Ok(out)
301 }
302
303 pub fn read_u8(&mut self) -> Result<u8> {
305 Ok(self.read_exact(1)?[0])
306 }
307
308 pub fn read_u16(&mut self) -> Result<u16> {
310 Ok(u16::from_le_bytes(self.read_array()?))
311 }
312
313 pub fn read_u32(&mut self) -> Result<u32> {
315 Ok(u32::from_le_bytes(self.read_array()?))
316 }
317
318 pub fn read_u64(&mut self) -> Result<u64> {
320 Ok(u64::from_le_bytes(self.read_array()?))
321 }
322
323 pub fn read_u128(&mut self) -> Result<u128> {
325 Ok(u128::from_le_bytes(self.read_array()?))
326 }
327
328 pub fn read_bool(&mut self) -> Result<bool> {
332 match self.read_u8()? {
333 0 => Ok(false),
334 1 => Ok(true),
335 _ => Err(Error::new(ERR_CODEC)),
336 }
337 }
338
339 pub fn read_raw(&mut self, len: usize) -> Result<&'a [u8]> {
341 self.read_exact(len)
342 }
343
344 pub fn read_bytes(&mut self) -> Result<&'a [u8]> {
348 let len = self.read_u32()? as usize;
349 self.read_exact(len)
350 }
351
352 pub fn read_string(&mut self) -> Result<String> {
356 let bytes = self.read_bytes()?;
357 let value = core::str::from_utf8(bytes).map_err(|_| Error::new(ERR_CODEC_UTF8))?;
358 Ok(String::from(value))
359 }
360
361 pub fn read_codec<T: BytesCodec>(&mut self) -> Result<T> {
363 let bytes = self.read_bytes()?;
364 T::decode_bytes(bytes)
365 }
366
367 pub fn finish(self) -> Result<()> {
380 if self.cursor == self.bytes.len() {
381 Ok(())
382 } else {
383 Err(Error::new(ERR_CODEC))
384 }
385 }
386}
387
388impl Codec32 for [u8; 32] {
393 fn encode_32(&self) -> [u8; 32] {
394 *self
395 }
396
397 fn decode_32(bytes: &[u8; 32]) -> Result<Self> {
398 Ok(*bytes)
399 }
400}
401
402impl Codec32 for bool {
403 fn encode_32(&self) -> [u8; 32] {
404 let mut out = [0u8; 32];
405 out[0] = if *self { 1 } else { 0 };
406 out
407 }
408
409 fn decode_32(bytes: &[u8; 32]) -> Result<Self> {
410 match bytes[0] {
411 0 => Ok(false),
412 1 => Ok(true),
413 _ => Err(Error::new(ERR_CODEC)),
414 }
415 }
416}
417
418macro_rules! impl_codec32_int {
420 ($ty:ty, $width:expr) => {
421 impl Codec32 for $ty {
422 fn encode_32(&self) -> [u8; 32] {
423 let mut out = [0u8; 32];
424 out[..$width].copy_from_slice(&self.to_le_bytes());
425 out
426 }
427
428 fn decode_32(bytes: &[u8; 32]) -> Result<Self> {
429 let mut raw = [0u8; $width];
430 raw.copy_from_slice(&bytes[..$width]);
431 Ok(<$ty>::from_le_bytes(raw))
432 }
433 }
434 };
435}
436
437impl_codec32_int!(u8, 1);
438impl_codec32_int!(u16, 2);
439impl_codec32_int!(u32, 4);
440impl_codec32_int!(u64, 8);
441impl_codec32_int!(u128, 16);
442impl_codec32_int!(i8, 1);
443impl_codec32_int!(i16, 2);
444impl_codec32_int!(i32, 4);
445impl_codec32_int!(i64, 8);
446impl_codec32_int!(i128, 16);
447
448impl BytesCodec for bool {
453 fn encode_bytes(&self) -> Vec<u8> {
454 vec![if *self { 1 } else { 0 }]
455 }
456
457 fn decode_bytes(bytes: &[u8]) -> Result<Self> {
458 if bytes.len() != 1 {
459 return Err(Error::new(ERR_CODEC));
460 }
461 match bytes[0] {
462 0 => Ok(false),
463 1 => Ok(true),
464 _ => Err(Error::new(ERR_CODEC)),
465 }
466 }
467}
468
469macro_rules! impl_bytescodec_int {
471 ($ty:ty, $width:expr) => {
472 impl BytesCodec for $ty {
473 fn encode_bytes(&self) -> Vec<u8> {
474 self.to_le_bytes().to_vec()
475 }
476
477 fn decode_bytes(bytes: &[u8]) -> Result<Self> {
478 if bytes.len() != $width {
479 return Err(Error::new(ERR_CODEC));
480 }
481 let mut raw = [0u8; $width];
482 raw.copy_from_slice(bytes);
483 Ok(<$ty>::from_le_bytes(raw))
484 }
485 }
486 };
487}
488
489impl_bytescodec_int!(u8, 1);
490impl_bytescodec_int!(u16, 2);
491impl_bytescodec_int!(u32, 4);
492impl_bytescodec_int!(u64, 8);
493impl_bytescodec_int!(u128, 16);
494impl_bytescodec_int!(i8, 1);
495impl_bytescodec_int!(i16, 2);
496impl_bytescodec_int!(i32, 4);
497impl_bytescodec_int!(i64, 8);
498impl_bytescodec_int!(i128, 16);
499
500impl BytesCodec for Vec<u8> {
501 fn encode_bytes(&self) -> Vec<u8> {
502 self.clone()
503 }
504
505 fn decode_bytes(bytes: &[u8]) -> Result<Self> {
506 Ok(bytes.to_vec())
507 }
508}
509
510impl<const N: usize> BytesCodec for [u8; N] {
511 fn encode_bytes(&self) -> Vec<u8> {
512 self.to_vec()
513 }
514
515 fn decode_bytes(bytes: &[u8]) -> Result<Self> {
516 if bytes.len() != N {
517 return Err(Error::new(ERR_CODEC));
518 }
519 let mut out = [0u8; N];
520 out.copy_from_slice(bytes);
521 Ok(out)
522 }
523}
524
525impl BytesCodec for String {
526 fn encode_bytes(&self) -> Vec<u8> {
527 self.as_bytes().to_vec()
528 }
529
530 fn decode_bytes(bytes: &[u8]) -> Result<Self> {
531 let s = core::str::from_utf8(bytes).map_err(|_| Error::new(ERR_CODEC_UTF8))?;
532 Ok(String::from(s))
533 }
534}
535
536impl<T: BytesCodec> BytesCodec for Option<T> {
537 fn encode_bytes(&self) -> Vec<u8> {
538 match self {
539 Some(value) => {
540 let mut out = Vec::with_capacity(1);
541 out.push(1);
542 out.extend_from_slice(&value.encode_bytes());
543 out
544 }
545 None => vec![0],
546 }
547 }
548
549 fn decode_bytes(bytes: &[u8]) -> Result<Self> {
550 if bytes.is_empty() {
551 return Err(Error::new(ERR_CODEC));
552 }
553 match bytes[0] {
554 0 => {
555 if bytes.len() != 1 {
556 return Err(Error::new(ERR_CODEC));
557 }
558 Ok(None)
559 }
560 1 => Ok(Some(T::decode_bytes(&bytes[1..])?)),
561 _ => Err(Error::new(ERR_CODEC)),
562 }
563 }
564}
565
566#[cfg(test)]
567mod tests {
568 use super::*;
569 use alloc::string::String;
570
571 #[derive(crate::BytesCodec, crate::Codec32, Debug, PartialEq, Eq)]
572 struct SmallRecord {
573 id: u16,
574 enabled: bool,
575 }
576
577 #[derive(crate::BytesCodec, Debug, PartialEq, Eq)]
578 enum Action {
579 Inc(u64),
580 Set { value: u64 },
581 Reset,
582 }
583
584 #[test]
585 fn codec32_roundtrip_u64() {
586 let raw = 55u64.encode_32();
587 let decoded = u64::decode_32(&raw).unwrap();
588 assert_eq!(decoded, 55);
589 }
590
591 #[test]
592 fn bytescodec_roundtrip_string() {
593 let s = String::from("hello");
594 let bytes = s.encode_bytes();
595 let decoded = String::decode_bytes(&bytes).unwrap();
596 assert_eq!(decoded, "hello");
597 }
598
599 #[test]
600 fn encoder_decoder_roundtrip() {
601 let mut enc = Encoder::new();
602 enc.push_u64(99);
603 enc.push_bool(true);
604 enc.push_string("abc");
605
606 let bytes = enc.into_vec();
607 let mut dec = Decoder::new(&bytes);
608 assert_eq!(dec.read_u64().unwrap(), 99);
609 assert!(dec.read_bool().unwrap());
610 assert_eq!(dec.read_string().unwrap(), "abc");
611 dec.finish().unwrap();
612 }
613
614 #[test]
615 fn derive_bytescodec_roundtrip_struct_and_enum() {
616 let rec = SmallRecord {
617 id: 7,
618 enabled: true,
619 };
620 let rec_bytes = rec.encode_bytes();
621 let rec_decoded = SmallRecord::decode_bytes(&rec_bytes).unwrap();
622 assert_eq!(rec, rec_decoded);
623
624 let action = Action::Set { value: 44 };
625 let action_bytes = action.encode_bytes();
626 let action_decoded = Action::decode_bytes(&action_bytes).unwrap();
627 assert_eq!(action, action_decoded);
628 }
629
630 #[test]
631 fn derive_codec32_roundtrip_small_record() {
632 let rec = SmallRecord {
633 id: 42,
634 enabled: false,
635 };
636 let raw = rec.encode_32();
637 let decoded = SmallRecord::decode_32(&raw).unwrap();
638 assert_eq!(decoded, rec);
639 }
640}