1#![no_std]
37#![warn(missing_debug_implementations)]
38#![warn(non_ascii_idents)]
39#![warn(single_use_lifetimes)]
40#![warn(unused_extern_crates)]
41#![warn(unused_import_braces)]
42#![warn(unused_lifetimes)]
43#![warn(unused_qualifications)]
44#![warn(variant_size_differences)]
45#![warn(clippy::cargo)]
46#![warn(clippy::nursery)]
47#![warn(clippy::pedantic)]
48#![allow(clippy::inline_always)]
49#![warn(clippy::assertions_on_result_states)]
51#![warn(clippy::clone_on_ref_ptr)]
52#![warn(clippy::dbg_macro)]
53#![warn(clippy::decimal_literal_representation)]
54#![warn(clippy::default_union_representation)]
55#![warn(clippy::deref_by_slicing)]
56#![warn(clippy::empty_drop)]
57#![warn(clippy::empty_structs_with_brackets)]
58#![warn(clippy::exhaustive_enums)]
59#![warn(clippy::exit)]
60#![warn(clippy::fn_to_numeric_cast_any)]
61#![warn(clippy::format_push_string)]
62#![warn(clippy::get_unwrap)]
63#![warn(clippy::if_then_some_else_none)]
64#![warn(clippy::lossy_float_literal)]
65#![warn(clippy::missing_enforced_import_renames)]
66#![warn(clippy::mixed_read_write_in_expression)]
67#![warn(clippy::mod_module_files)]
68#![warn(clippy::mutex_atomic)]
69#![warn(clippy::pattern_type_mismatch)]
70#![warn(clippy::print_stdout)]
71#![warn(clippy::rc_buffer)]
72#![warn(clippy::rc_mutex)]
73#![warn(clippy::rest_pat_in_fully_bound_structs)]
74#![warn(clippy::str_to_string)]
75#![warn(clippy::string_add)]
76#![warn(clippy::string_to_string)]
77#![warn(clippy::suspicious_xor_used_as_pow)]
78#![warn(clippy::todo)]
79#![warn(clippy::try_err)]
80#![warn(clippy::undocumented_unsafe_blocks)]
81#![warn(clippy::unnecessary_safety_comment)]
82#![warn(clippy::unnecessary_safety_doc)]
83#![warn(clippy::unnecessary_self_imports)]
84#![warn(clippy::unneeded_field_pattern)]
85#![warn(clippy::unseparated_literal_suffix)]
86
87use core::ops::{Deref, DerefMut};
88use core::{mem, ptr, slice};
89
90use smallvec::SmallVec;
91
92const INLINE_CAP: usize = 32;
96
97pub trait Pack {
99 #[must_use]
101 fn append(&mut self) -> Packer;
102
103 #[must_use]
106 fn at(&mut self, i: usize) -> Packer;
107}
108
109pub trait Unpack {
111 fn unpack(&self) -> Unpacker;
113}
114
115impl<T: AsRef<[u8]>> Unpack for T {
117 #[inline(always)]
118 fn unpack(&self) -> Unpacker {
119 Unpacker::new(self.as_ref())
120 }
121}
122
123#[derive(Clone, Debug, Default)]
134#[must_use]
135pub struct StructBuf {
136 lim: usize,
137 b: SmallVec<[u8; INLINE_CAP]>,
138}
139
140impl StructBuf {
141 #[inline(always)]
145 pub const fn new(lim: usize) -> Self {
146 Self {
147 lim,
148 b: SmallVec::new_const(),
149 }
150 }
151
152 #[inline(always)]
155 pub const fn none() -> Self {
156 Self::new(0)
157 }
158
159 #[inline(always)]
163 pub fn with_capacity(cap: usize) -> Self {
164 Self {
165 lim: cap,
166 b: SmallVec::with_capacity(cap),
167 }
168 }
169
170 #[inline(always)]
172 #[must_use]
173 pub fn len(&self) -> usize {
174 self.b.len()
175 }
176
177 #[inline(always)]
179 #[must_use]
180 pub fn capacity(&self) -> usize {
181 self.b.capacity().min(self.lim)
182 }
183
184 #[inline(always)]
186 #[must_use]
187 pub const fn lim(&self) -> usize {
188 self.lim
189 }
190
191 #[inline(always)]
194 #[must_use]
195 pub fn remaining(&self) -> usize {
196 self.lim - self.b.len()
197 }
198
199 #[inline(always)]
201 #[must_use]
202 pub fn is_empty(&self) -> bool {
203 self.b.is_empty()
204 }
205
206 #[inline(always)]
208 #[must_use]
209 pub fn is_full(&self) -> bool {
210 self.remaining() == 0
211 }
212
213 #[inline(always)]
215 #[must_use]
216 pub const fn is_none(&self) -> bool {
217 self.lim == 0
218 }
219
220 #[inline]
223 pub fn truncate(&mut self, n: usize) -> &mut Self {
224 if n < self.b.len() {
225 unsafe { self.b.set_len(n) }
227 }
228 self
229 }
230
231 #[inline(always)]
233 pub fn clear(&mut self) -> &mut Self {
234 self.truncate(0)
235 }
236
237 #[inline(always)]
239 pub fn take(&mut self) -> Self {
240 mem::replace(self, Self::none())
241 }
242
243 #[inline]
250 pub unsafe fn set_len(&mut self, n: usize) -> &mut Self {
251 debug_assert!(n <= self.capacity());
252 self.b.set_len(n);
253 self
254 }
255
256 #[inline]
258 pub fn set_lim(&mut self, n: usize) -> &mut Self {
259 self.lim = n;
260 self.truncate(n)
261 }
262
263 #[inline]
265 #[must_use]
266 pub const fn can_put_at(&self, i: usize, n: usize) -> bool {
267 let (sum, overflow) = i.overflowing_add(n);
268 sum <= self.lim && !overflow
269 }
270
271 #[inline(always)]
290 pub fn put_at<T: AsRef<[u8]>>(&mut self, i: usize, v: T) {
291 assert!(self.try_put_at(i, v), "buffer limit exceeded");
292 }
293
294 #[inline]
298 pub fn try_put_at<T: AsRef<[u8]>>(&mut self, i: usize, v: T) -> bool {
299 let v = v.as_ref();
300 let (j, overflow) = i.overflowing_add(v.len());
301 let ok = !overflow && j <= self.lim;
302 if ok {
303 unsafe { self.put_at_unchecked(i, j, v) };
305 }
306 ok
307 }
308
309 unsafe fn put_at_unchecked(&mut self, i: usize, j: usize, v: &[u8]) {
315 if self.b.capacity() < j {
316 self.b.grow(self.lim); }
318 let pad = i.saturating_sub(self.b.len());
319 let dst = self.b.as_mut_ptr();
320 if pad > 0 {
321 unsafe { dst.add(self.b.len()).write_bytes(0, pad) };
324 }
325 unsafe { dst.add(i).copy_from_nonoverlapping(v.as_ptr(), v.len()) };
327 if j > self.b.len() {
328 unsafe { self.b.set_len(j) };
330 }
331 }
332}
333
334impl Pack for StructBuf {
335 #[inline(always)]
336 fn append(&mut self) -> Packer {
337 self.at(self.b.len())
338 }
339
340 #[inline(always)]
341 fn at(&mut self, i: usize) -> Packer {
342 Packer { i, b: self }
343 }
344}
345
346impl AsRef<[u8]> for StructBuf {
347 #[inline(always)]
348 fn as_ref(&self) -> &[u8] {
349 &self.b
350 }
351}
352
353impl AsMut<[u8]> for StructBuf {
354 #[inline(always)]
355 fn as_mut(&mut self) -> &mut [u8] {
356 &mut self.b
357 }
358}
359
360impl Deref for StructBuf {
361 type Target = [u8];
362
363 #[inline(always)]
364 fn deref(&self) -> &Self::Target {
365 &self.b
366 }
367}
368
369impl DerefMut for StructBuf {
370 #[inline(always)]
371 fn deref_mut(&mut self) -> &mut Self::Target {
372 &mut self.b
373 }
374}
375
376#[derive(Debug)]
387pub struct Packer<'a> {
388 i: usize,
389 b: &'a mut StructBuf, }
391
392impl Packer<'_> {
393 #[inline(always)]
395 #[must_use]
396 pub const fn position(&self) -> usize {
397 self.i
398 }
399
400 #[inline]
402 #[must_use]
403 pub fn remaining(&self) -> usize {
404 self.b.lim.saturating_sub(self.i)
405 }
406
407 #[inline(always)]
409 pub fn skip(&mut self, n: usize) -> &mut Self {
410 self.i += n;
411 self
412 }
413
414 #[inline(always)]
416 pub fn bool<T: Into<bool>>(&mut self, v: T) -> &mut Self {
417 self.u8(v.into())
418 }
419
420 #[inline(always)]
422 pub fn u8<T: Into<u8>>(&mut self, v: T) -> &mut Self {
423 self.put([v.into()])
424 }
425
426 #[inline(always)]
428 pub fn u16<T: Into<u16>>(&mut self, v: T) -> &mut Self {
429 self.put(v.into().to_le_bytes())
430 }
431
432 #[inline(always)]
438 pub fn u24<T: Into<u32>>(&mut self, v: T) -> &mut Self {
439 let v = v.into().to_le_bytes();
440 assert_eq!(v[3], 0);
441 self.put(&v[..3])
442 }
443
444 #[inline(always)]
446 pub fn u32<T: Into<u32>>(&mut self, v: T) -> &mut Self {
447 self.put(v.into().to_le_bytes())
448 }
449
450 #[inline(always)]
452 pub fn u64<T: Into<u64>>(&mut self, v: T) -> &mut Self {
453 self.put(v.into().to_le_bytes())
454 }
455
456 #[inline(always)]
458 pub fn u128<T: Into<u128>>(&mut self, v: T) -> &mut Self {
459 self.put(v.into().to_le_bytes())
460 }
461
462 #[inline(always)]
464 pub fn i8<T: Into<i8>>(&mut self, v: T) -> &mut Self {
465 #[allow(clippy::cast_sign_loss)]
466 self.put([v.into() as u8])
467 }
468
469 #[inline(always)]
471 pub fn i16<T: Into<i16>>(&mut self, v: T) -> &mut Self {
472 self.put(v.into().to_le_bytes())
473 }
474
475 #[inline(always)]
477 pub fn i32<T: Into<i32>>(&mut self, v: T) -> &mut Self {
478 self.put(v.into().to_le_bytes())
479 }
480
481 #[inline(always)]
483 pub fn i64<T: Into<i64>>(&mut self, v: T) -> &mut Self {
484 self.put(v.into().to_le_bytes())
485 }
486
487 #[inline(always)]
489 pub fn i128<T: Into<i128>>(&mut self, v: T) -> &mut Self {
490 self.put(v.into().to_le_bytes())
491 }
492
493 #[inline(always)]
495 #[must_use]
496 pub const fn can_put(&self, n: usize) -> bool {
497 self.b.can_put_at(self.i, n)
498 }
499
500 #[inline]
502 pub fn put<T: AsRef<[u8]>>(&mut self, v: T) -> &mut Self {
503 let v = v.as_ref();
504 self.b.put_at(self.i, v);
505 self.i += v.len();
506 self
507 }
508}
509
510impl AsRef<[u8]> for Packer<'_> {
511 #[inline]
512 fn as_ref(&self) -> &[u8] {
513 unsafe { self.b.get_unchecked(self.b.len().min(self.i)..) }
515 }
516}
517
518impl AsMut<[u8]> for Packer<'_> {
519 #[inline]
520 fn as_mut(&mut self) -> &mut [u8] {
521 let i = self.b.len().min(self.i);
522 unsafe { self.b.get_unchecked_mut(i..) }
524 }
525}
526
527impl From<&mut Packer<'_>> for () {
529 #[inline(always)]
530 fn from(_: &mut Packer) -> Self {}
531}
532
533#[allow(single_use_lifetimes)]
541#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
542#[must_use]
543#[repr(transparent)]
544pub struct Unpacker<'a>(&'a [u8]);
545
546impl<'a> Unpacker<'a> {
547 #[inline(always)]
549 pub const fn new(b: &'a [u8]) -> Self {
550 Self(b)
551 }
552
553 #[inline(always)]
555 pub const fn invalid() -> Self {
556 Self(Self::err())
557 }
558
559 #[inline(always)]
562 #[must_use]
563 pub const fn into_inner(self) -> &'a [u8] {
564 self.0
565 }
566
567 #[inline(always)]
569 #[must_use]
570 pub const fn len(&self) -> usize {
571 self.0.len()
572 }
573
574 #[inline(always)]
576 #[must_use]
577 pub const fn is_empty(&self) -> bool {
578 self.0.is_empty()
579 }
580
581 #[inline(always)]
584 #[must_use]
585 pub fn is_ok(&self) -> bool {
586 !ptr::eq(self.0, Self::err())
587 }
588
589 #[inline]
594 pub fn take(&mut self) -> Self {
595 let empty = unsafe { self.0.get_unchecked(self.0.len()..) };
597 Self(mem::replace(&mut self.0, empty))
598 }
599
600 #[inline]
603 #[must_use]
604 pub fn map<T>(mut self, f: impl FnOnce(&mut Self) -> T) -> Option<T> {
605 let v = f(&mut self);
606 (self.is_ok() && self.0.is_empty()).then_some(v)
607 }
608
609 #[inline(always)]
612 #[must_use]
613 pub fn map_or<T>(self, default: T, f: impl FnOnce(&mut Self) -> T) -> T {
614 self.map(f).unwrap_or(default)
615 }
616
617 #[inline(always)]
620 pub fn map_or_else<T>(self, default: impl FnOnce() -> T, f: impl FnOnce(&mut Self) -> T) -> T {
621 self.map(f).unwrap_or_else(default)
622 }
623
624 #[inline]
627 pub const fn split_at(&self, i: usize) -> (Self, Self) {
628 let Some(rem) = self.0.len().checked_sub(i) else {
629 return (Self(Self::err()), Self(Self::err()));
630 };
631 let p = self.0.as_ptr();
632 unsafe {
634 (
635 Self(slice::from_raw_parts(p, i)),
636 Self(slice::from_raw_parts(p.add(i), rem)),
637 )
638 }
639 }
640
641 #[inline]
659 pub fn skip(&mut self, n: usize) -> Option<Self> {
660 let (a, b) = self.split_at(n);
661 self.0 = b.0;
662 a.is_ok().then_some(a)
663 }
664
665 #[inline(always)]
668 #[must_use]
669 pub fn bool(&mut self) -> bool {
670 self.u8() != 0
671 }
672
673 #[inline(always)]
675 #[must_use]
676 pub fn u8(&mut self) -> u8 {
677 unsafe { self.read() }
679 }
680
681 #[inline(always)]
683 #[must_use]
684 pub fn u16(&mut self) -> u16 {
685 u16::from_le(unsafe { self.read() })
687 }
688
689 #[inline(always)]
691 #[must_use]
692 pub fn u32(&mut self) -> u32 {
693 u32::from_le(unsafe { self.read() })
695 }
696
697 #[inline(always)]
699 #[must_use]
700 pub fn u64(&mut self) -> u64 {
701 u64::from_le(unsafe { self.read() })
703 }
704
705 #[inline(always)]
707 #[must_use]
708 pub fn u128(&mut self) -> u128 {
709 u128::from_le(unsafe { self.read() })
711 }
712
713 #[inline(always)]
715 #[must_use]
716 pub fn i8(&mut self) -> i8 {
717 unsafe { self.read() }
719 }
720
721 #[inline(always)]
723 #[must_use]
724 pub fn i16(&mut self) -> i16 {
725 i16::from_le(unsafe { self.read() })
727 }
728
729 #[inline(always)]
731 #[must_use]
732 pub fn i32(&mut self) -> i32 {
733 i32::from_le(unsafe { self.read() })
735 }
736
737 #[inline(always)]
739 #[must_use]
740 pub fn i64(&mut self) -> i64 {
741 i64::from_le(unsafe { self.read() })
743 }
744
745 #[inline(always)]
747 #[must_use]
748 pub fn i128(&mut self) -> i128 {
749 i128::from_le(unsafe { self.read() })
751 }
752
753 #[inline(always)]
755 #[must_use]
756 pub fn bytes<const N: usize>(&mut self) -> [u8; N] {
757 if let Some(rem) = self.0.len().checked_sub(N) {
758 unsafe {
760 let p = self.0.as_ptr();
761 self.0 = slice::from_raw_parts(p.add(N), rem);
762 *p.cast()
763 }
764 } else {
765 self.0 = Self::err();
766 [0; N]
767 }
768 }
769
770 #[inline]
778 #[must_use]
779 pub unsafe fn read<T: Default>(&mut self) -> T {
780 if let Some(rem) = self.0.len().checked_sub(mem::size_of::<T>()) {
781 let p = self.0.as_ptr().cast::<T>();
783 self.0 = slice::from_raw_parts(p.add(1).cast(), rem);
784 p.read_unaligned()
785 } else {
786 self.0 = Self::err();
787 T::default()
788 }
789 }
790
791 #[inline(always)]
794 #[must_use]
795 const fn err() -> &'static [u8] {
796 unsafe { slice::from_raw_parts(ptr::NonNull::dangling().as_ptr(), 0) }
799 }
800}
801
802impl<'a> AsRef<[u8]> for Unpacker<'a> {
803 #[inline(always)]
804 #[must_use]
805 fn as_ref(&self) -> &'a [u8] {
806 self.0
807 }
808}
809
810#[cfg(test)]
811mod tests {
812 use super::*;
813
814 #[test]
815 fn packer() {
816 let mut b = StructBuf::new(4);
817 assert_eq!(b.len(), 0);
818 assert_eq!(b.capacity(), 4);
819 assert_eq!(b.lim(), 4);
820
821 b.append().u8(1);
822 assert_eq!(b.len(), 1);
823 assert_eq!(b.as_ref(), &[1]);
824
825 b.append().u8(2).u16(0x0403_u16);
826 assert_eq!(b.len(), 4);
827 assert_eq!(b.as_ref(), &[1, 2, 3, 4]);
828 }
829
830 #[test]
831 #[should_panic]
832 fn packer_limit() {
833 let mut b = StructBuf::new(4);
834 b.append().u8(1).u16(2_u16);
835 b.append().u16(3_u16);
836 }
837
838 #[test]
839 fn packer_overwrite() {
840 let mut b = StructBuf::new(4);
841 b.append().put([1, 2, 3, 4]);
842 assert_eq!(b.as_ref(), &[1, 2, 3, 4]);
843 b.at(1).u16(0x0203_u16);
844 assert_eq!(b.as_ref(), &[1, 3, 2, 4]);
845 }
846
847 #[test]
848 fn packer_pad() {
849 let mut b = StructBuf::with_capacity(INLINE_CAP + 1);
850 unsafe { b.as_mut_ptr().write_bytes(0xFF, b.capacity()) };
852 b.at(b.capacity() - 1).u8(1);
853 assert!(&b[..INLINE_CAP].iter().all(|&v| v == 0));
854 assert_eq!(b[INLINE_CAP], 1);
855
856 b.clear();
857 b.put_at(4, []);
858 assert_eq!(b.as_ref(), &[0, 0, 0, 0]);
859 }
860
861 #[test]
862 fn unpacker() {
863 let mut p = Unpacker::new(&[1, 2, 3]);
864 assert_eq!(p.u8(), 1);
865 assert!(p.is_ok());
866 assert_eq!(p.u16(), 0x0302);
867 assert!(p.is_ok());
868 assert_eq!(p.u8(), 0);
869 assert!(!p.is_ok());
870
871 let mut p = Unpacker::new(&[1]);
872 assert_eq!(p.u16(), 0);
873 assert!(!p.is_ok());
874 assert_eq!(p.u32(), 0);
875
876 let mut p = Unpacker::new(&[1, 2, 3]);
877 assert_eq!(p.bytes::<2>(), [1, 2]);
878 assert_eq!(p.bytes::<3>(), [0, 0, 0]);
879 }
880
881 #[test]
882 fn unpacker_take() {
883 let mut p = Unpacker::new(&[1, 2, 3]);
884 assert_eq!(p.u8(), 1);
885
886 let mut v = p.take();
887 assert!(p.is_ok());
888 assert!(p.is_empty());
889 assert_eq!((v.u8(), v.u8()), (2, 3));
890 assert!(v.is_ok());
891
892 assert_eq!(p.u64(), 0);
893 assert!(!p.is_ok());
894 let v = p.take();
895 assert!(!v.is_ok());
896 }
897
898 #[test]
899 fn unpacker_skip() {
900 let mut p = Unpacker::new(&[1, 2, 3]);
901 let mut v = p.skip(2).unwrap();
902
903 assert_eq!((v.u8(), v.u8()), (1, 2));
904 assert_eq!(p.u8(), 3);
905
906 assert!(p.skip(0).unwrap().is_ok());
907 assert!(p.is_ok());
908 assert!(p.skip(1).is_none());
909 assert!(!p.is_ok());
910 }
911}