1#![no_std]
17#![warn(missing_docs)]
19#![doc(test(attr(warn(unused))))]
20#![warn(clippy::return_self_not_must_use)]
22
23#[cfg(feature = "alloc")]
24extern crate alloc;
25
26#[cfg(feature = "std")]
27extern crate std;
28
29pub extern crate encoding;
30
31#[cfg(feature = "hashes")]
32pub extern crate hashes;
33
34#[cfg(feature = "std")]
35mod bridge;
36mod error;
37
38#[cfg(feature = "hashes")]
39mod hash;
40
41#[cfg(all(not(feature = "std"), feature = "alloc"))]
42use alloc::vec::Vec;
43use core::cmp;
44#[cfg(feature = "std")]
45use std::vec::Vec;
46
47use encoding::{Decodable, Decoder, Encoder};
48
49#[rustfmt::skip] pub use self::error::{Error, ErrorKind};
51#[cfg(feature = "std")]
52pub use self::bridge::{FromStd, ToStd};
53#[cfg(feature = "hashes")]
54pub use self::hash::hash_reader;
55
56pub type Result<T> = core::result::Result<T, Error>;
58
59pub trait Read {
63 fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
73
74 #[inline]
80 fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
81 while !buf.is_empty() {
82 match self.read(buf) {
83 Ok(0) => return Err(ErrorKind::UnexpectedEof.into()),
84 Ok(len) => buf = &mut buf[len..],
85 Err(e) if e.kind() == ErrorKind::Interrupted => {}
86 Err(e) => return Err(e),
87 }
88 }
89 Ok(())
90 }
91
92 #[inline]
94 fn take(self, limit: u64) -> Take<Self>
95 where
96 Self: Sized,
97 {
98 Take { reader: self, remaining: limit }
99 }
100
101 #[doc(alias = "read_to_end")]
116 #[cfg(feature = "alloc")]
117 #[inline]
118 fn read_to_limit(&mut self, buf: &mut Vec<u8>, limit: u64) -> Result<usize> {
119 self.take(limit).read_to_end(buf)
120 }
121}
122
123pub trait BufRead: Read {
125 fn fill_buf(&mut self) -> Result<&[u8]>;
131
132 fn consume(&mut self, amount: usize);
138}
139
140#[derive(Debug)]
144pub struct Take<R> {
145 reader: R,
146 remaining: u64,
147}
148
149impl<R: Read> Take<R> {
150 #[cfg(feature = "alloc")]
162 #[inline]
163 pub fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
164 let mut read: usize = 0;
165 let mut chunk = [0u8; 64];
166 loop {
167 match self.read(&mut chunk) {
168 Ok(0) => break,
169 Ok(n) => {
170 buf.extend_from_slice(&chunk[0..n]);
171 read += n;
172 }
173 Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
174 Err(e) => return Err(e),
175 };
176 }
177 Ok(read)
178 }
179}
180
181impl<R: Read> Read for Take<R> {
182 #[inline]
183 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
184 let len = cmp::min(buf.len(), self.remaining.try_into().unwrap_or(buf.len()));
185 let read = self.reader.read(&mut buf[..len])?;
186 self.remaining -= read.try_into().unwrap_or(self.remaining);
187 Ok(read)
188 }
189}
190
191impl<R: BufRead> BufRead for Take<R> {
193 #[inline]
194 fn fill_buf(&mut self) -> Result<&[u8]> {
195 if self.remaining == 0 {
197 return Ok(&[]);
198 }
199
200 let buf = self.reader.fill_buf()?;
201 let cap = cmp::min(buf.len() as u64, self.remaining) as usize;
204 Ok(&buf[..cap])
205 }
206
207 #[inline]
208 fn consume(&mut self, amount: usize) {
209 assert!(amount as u64 <= self.remaining);
210 self.remaining -= amount as u64;
211 self.reader.consume(amount);
212 }
213}
214
215impl<T: Read + ?Sized> Read for &'_ mut T {
216 #[inline]
217 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
218 (**self).read(buf)
219 }
220
221 #[inline]
222 fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
223 (**self).read_exact(buf)
224 }
225}
226
227impl<T: BufRead + ?Sized> BufRead for &'_ mut T {
228 #[inline]
229 fn fill_buf(&mut self) -> Result<&[u8]> {
230 (**self).fill_buf()
231 }
232
233 #[inline]
234 fn consume(&mut self, amount: usize) {
235 (**self).consume(amount);
236 }
237}
238
239impl Read for &[u8] {
240 #[inline]
241 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
242 let cnt = cmp::min(self.len(), buf.len());
243 buf[..cnt].copy_from_slice(&self[..cnt]);
244 *self = &self[cnt..];
245 Ok(cnt)
246 }
247}
248
249impl BufRead for &[u8] {
250 #[inline]
251 fn fill_buf(&mut self) -> Result<&[u8]> {
252 Ok(self)
253 }
254
255 #[inline]
257 fn consume(&mut self, amount: usize) {
258 *self = &self[amount..];
259 }
260}
261
262#[derive(Clone, Debug, Default, Eq, PartialEq)]
264pub struct Cursor<T> {
265 inner: T,
266 pos: u64,
267}
268
269impl<T: AsRef<[u8]>> Cursor<T> {
270 #[inline]
272 pub const fn new(inner: T) -> Self {
273 Self { inner, pos: 0 }
274 }
275
276 #[inline]
278 pub const fn position(&self) -> u64 {
279 self.pos
280 }
281
282 #[inline]
289 pub fn set_position(&mut self, position: u64) {
290 self.pos = position;
291 }
292
293 #[inline]
297 pub fn into_inner(self) -> T {
298 self.inner
299 }
300
301 #[inline]
305 pub const fn get_ref(&self) -> &T {
306 &self.inner
307 }
308
309 #[inline]
313 pub fn get_mut(&mut self) -> &mut T {
314 &mut self.inner
315 }
316}
317
318impl<T: AsRef<[u8]>> Read for Cursor<T> {
319 #[inline]
320 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
321 let inner: &[u8] = self.inner.as_ref();
322 let start_pos = self.pos.try_into().unwrap_or(inner.len());
323 if start_pos >= self.inner.as_ref().len() {
324 return Ok(0);
325 }
326
327 let read = core::cmp::min(inner.len().saturating_sub(start_pos), buf.len());
328 buf[..read].copy_from_slice(&inner[start_pos..start_pos + read]);
329 self.pos = self.pos.saturating_add(read.try_into().unwrap_or(u64::MAX ));
330 Ok(read)
331 }
332}
333
334impl<T: AsRef<[u8]>> BufRead for Cursor<T> {
335 #[inline]
336 fn fill_buf(&mut self) -> Result<&[u8]> {
337 let inner: &[u8] = self.inner.as_ref();
338 let pos = self.pos.min(inner.len() as u64) as usize;
339 Ok(&inner[pos..])
340 }
341
342 #[inline]
343 fn consume(&mut self, amount: usize) {
344 self.pos = self.pos.saturating_add(amount as u64);
345 }
346}
347
348impl<T: AsMut<[u8]>> Write for Cursor<T> {
349 #[inline]
350 fn write(&mut self, buf: &[u8]) -> Result<usize> {
351 let write_slice = self.inner.as_mut();
352 let pos = cmp::min(self.pos, write_slice.len() as u64);
353 let amt = (&mut write_slice[(pos as usize)..]).write(buf)?;
354 self.pos += amt as u64;
355 Ok(amt)
356 }
357
358 #[inline]
359 fn flush(&mut self) -> Result<()> {
360 Ok(())
361 }
362}
363
364pub trait Write {
368 fn write(&mut self, buf: &[u8]) -> Result<usize>;
374
375 fn flush(&mut self) -> Result<()>;
382
383 #[inline]
389 fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
390 while !buf.is_empty() {
391 match self.write(buf) {
392 Ok(0) => return Err(ErrorKind::UnexpectedEof.into()),
393 Ok(len) => buf = &buf[len..],
394 Err(e) if e.kind() == ErrorKind::Interrupted => {}
395 Err(e) => return Err(e),
396 }
397 }
398 Ok(())
399 }
400}
401
402impl<T: Write> Write for &'_ mut T {
403 #[inline]
404 fn write(&mut self, buf: &[u8]) -> Result<usize> {
405 (**self).write(buf)
406 }
407
408 #[inline]
409 fn write_all(&mut self, buf: &[u8]) -> Result<()> {
410 (**self).write_all(buf)
411 }
412
413 #[inline]
414 fn flush(&mut self) -> Result<()> {
415 (**self).flush()
416 }
417}
418
419#[cfg(feature = "alloc")]
420impl Write for alloc::vec::Vec<u8> {
421 #[inline]
422 fn write(&mut self, buf: &[u8]) -> Result<usize> {
423 self.extend_from_slice(buf);
424 Ok(buf.len())
425 }
426
427 #[inline]
428 fn flush(&mut self) -> Result<()> {
429 Ok(())
430 }
431}
432
433impl Write for &mut [u8] {
434 #[inline]
435 fn write(&mut self, buf: &[u8]) -> Result<usize> {
436 let cnt = core::cmp::min(self.len(), buf.len());
437 self[..cnt].copy_from_slice(&buf[..cnt]);
438 *self = &mut core::mem::take(self)[cnt..];
439 Ok(cnt)
440 }
441
442 #[inline]
443 fn flush(&mut self) -> Result<()> {
444 Ok(())
445 }
446}
447
448#[derive(Clone, Copy, Debug, Default)]
452pub struct Sink;
453
454impl Write for Sink {
455 #[inline]
456 fn write(&mut self, buf: &[u8]) -> Result<usize> {
457 Ok(buf.len())
458 }
459
460 #[inline]
461 fn write_all(&mut self, _: &[u8]) -> Result<()> {
462 Ok(())
463 }
464
465 #[inline]
466 fn flush(&mut self) -> Result<()> {
467 Ok(())
468 }
469}
470
471#[inline]
475pub fn sink() -> Sink {
476 Sink
477}
478
479#[cfg(feature = "std")]
483#[inline]
484pub const fn from_std<T>(std_io: T) -> FromStd<T> {
485 FromStd::new(std_io)
486}
487
488#[cfg(feature = "std")]
492#[inline]
493pub fn from_std_mut<T>(std_io: &mut T) -> &mut FromStd<T> {
494 FromStd::new_mut(std_io)
495}
496
497pub fn encode_to_writer<T, W>(object: &T, writer: W) -> Result<()>
503where
504 T: encoding::Encodable + ?Sized,
505 W: Write,
506{
507 let mut encoder = object.encoder();
508 flush_to_writer(&mut encoder, writer)
509}
510
511pub fn flush_to_writer<T, W>(encoder: &mut T, mut writer: W) -> Result<()>
519where
520 T: Encoder + ?Sized,
521 W: Write,
522{
523 loop {
524 writer.write_all(encoder.current_chunk())?;
525 if !encoder.advance() {
526 break;
527 }
528 }
529 Ok(())
530}
531
532pub fn decode_from_read<T, R>(
545 mut reader: R,
546) -> core::result::Result<T, ReadError<<T::Decoder as Decoder>::Error>>
547where
548 T: Decodable,
549 R: BufRead,
550{
551 let mut decoder = T::decoder();
552
553 loop {
554 let mut buffer = match reader.fill_buf() {
555 Ok(buffer) => buffer,
556 Err(error) if error.kind() == ErrorKind::Interrupted => continue,
558 Err(error) => return Err(ReadError::Io(error)),
559 };
560
561 if buffer.is_empty() {
562 return decoder.end().map_err(ReadError::Decode);
564 }
565
566 let original_len = buffer.len();
567 let need_more = decoder.push_bytes(&mut buffer).map_err(ReadError::Decode)?;
568 let consumed = original_len - buffer.len();
569 reader.consume(consumed);
570
571 if !need_more {
572 return decoder.end().map_err(ReadError::Decode);
573 }
574 }
575}
576
577pub fn decode_from_read_unbuffered<T, R>(
596 reader: R,
597) -> core::result::Result<T, ReadError<<T::Decoder as Decoder>::Error>>
598where
599 T: Decodable,
600 R: Read,
601{
602 decode_from_read_unbuffered_with::<T, R, 4096>(reader)
603}
604
605pub fn decode_from_read_unbuffered_with<T, R, const BUFFER_SIZE: usize>(
623 mut reader: R,
624) -> core::result::Result<T, ReadError<<T::Decoder as Decoder>::Error>>
625where
626 T: Decodable,
627 R: Read,
628{
629 let mut decoder = T::decoder();
630 let mut buffer = [0u8; BUFFER_SIZE];
631
632 while decoder.read_limit() > 0 {
633 let clamped_buffer = &mut buffer[..decoder.read_limit().min(BUFFER_SIZE)];
635 match reader.read(clamped_buffer) {
636 Ok(0) => {
637 return decoder.end().map_err(ReadError::Decode);
639 }
640 Ok(bytes_read) => {
641 if !decoder
642 .push_bytes(&mut &clamped_buffer[..bytes_read])
643 .map_err(ReadError::Decode)?
644 {
645 return decoder.end().map_err(ReadError::Decode);
646 }
647 }
648 Err(ref e) if e.kind() == ErrorKind::Interrupted => {
649 }
651 Err(e) => return Err(ReadError::Io(e)),
652 }
653 }
654
655 decoder.end().map_err(ReadError::Decode)
656}
657
658#[derive(Debug)]
660pub enum ReadError<D> {
661 Io(Error),
663 Decode(D),
665}
666
667impl<D: core::fmt::Display> core::fmt::Display for ReadError<D> {
668 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
669 match self {
670 Self::Io(e) => write!(f, "I/O error: {}", e),
671 Self::Decode(e) => write!(f, "decode error: {}", e),
672 }
673 }
674}
675
676#[cfg(feature = "std")]
677impl<D> std::error::Error for ReadError<D>
678where
679 D: core::fmt::Debug + core::fmt::Display + std::error::Error + 'static,
680{
681 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
682 match self {
683 Self::Io(e) => Some(e),
684 Self::Decode(e) => Some(e),
685 }
686 }
687}
688
689#[cfg(feature = "std")]
690impl<D> From<Error> for ReadError<D> {
691 fn from(e: Error) -> Self {
692 Self::Io(e)
693 }
694}
695
696#[cfg(test)]
697mod tests {
698 #[cfg(all(not(feature = "std"), feature = "alloc"))]
699 use alloc::{string::ToString, vec};
700 #[cfg(feature = "std")]
701 use std::{string::ToString, vec};
702
703 use encoding::{ArrayDecoder, ArrayEncoder, UnexpectedEofError};
704
705 use super::*;
706
707 #[test]
708 fn buf_read_fill_and_consume_slice() {
709 let data = [0_u8, 1, 2];
710
711 let mut slice = &data[..];
712
713 let fill = BufRead::fill_buf(&mut slice).unwrap();
714 assert_eq!(fill.len(), 3);
715 assert_eq!(fill, &[0_u8, 1, 2]);
716 slice.consume(2);
717
718 let fill = BufRead::fill_buf(&mut slice).unwrap();
719 assert_eq!(fill.len(), 1);
720 assert_eq!(fill, &[2_u8]);
721 slice.consume(1);
722
723 let fill = BufRead::fill_buf(&mut slice).unwrap();
725 assert!(fill.is_empty());
726 }
727
728 #[test]
729 #[cfg(feature = "alloc")]
730 fn read_to_limit_greater_than_total_length() {
731 let s = "16-byte-string!!".to_string();
732 let mut reader = Cursor::new(&s);
733 let mut buf = vec![];
734
735 let read = reader.read_to_limit(&mut buf, 32).expect("failed to read to limit");
737 assert_eq!(read, s.len());
738 assert_eq!(&buf, s.as_bytes());
739 }
740
741 #[test]
742 #[cfg(feature = "alloc")]
743 fn read_to_limit_less_than_total_length() {
744 let s = "16-byte-string!!".to_string();
745 let mut reader = Cursor::new(&s);
746 let mut buf = vec![];
747
748 let read = reader.read_to_limit(&mut buf, 2).expect("failed to read to limit");
749 assert_eq!(read, 2);
750 assert_eq!(&buf, "16".as_bytes());
751 }
752
753 #[test]
754 #[cfg(feature = "std")]
755 fn set_position_past_end_read_returns_eof() {
756 const BUF_LEN: usize = 64; let mut buf = [0_u8; BUF_LEN]; let v = [1_u8; BUF_LEN];
760
761 let mut c = std::io::Cursor::new(v);
763 for pos in [BUF_LEN, BUF_LEN + 1, BUF_LEN * 2] {
764 c.set_position(pos as u64);
765 let read = c.read(&mut buf).unwrap();
766 assert_eq!(read, 0);
767 assert_eq!(buf[0], 0x00); }
769
770 let mut c = Cursor::new(v);
771 for pos in [BUF_LEN, BUF_LEN + 1, BUF_LEN * 2] {
772 c.set_position(pos as u64);
773 let read = c.read(&mut buf).unwrap();
774 assert_eq!(read, 0);
775 assert_eq!(buf[0], 0x00); }
777 }
778
779 #[test]
780 fn read_into_zero_length_buffer() {
781 use crate::Read as _;
782
783 const BUF_LEN: usize = 64;
784 let data = [1_u8; BUF_LEN];
785 let mut buf = [0_u8; BUF_LEN];
786
787 let mut slice = data.as_ref();
788 let mut take = Read::take(&mut slice, 32);
789
790 let read = take.read(&mut buf[0..0]).unwrap();
791 assert_eq!(read, 0);
792 assert_eq!(buf[0], 0x00); }
794
795 #[test]
796 #[cfg(feature = "alloc")]
797 fn take_and_read_to_end() {
798 const BUF_LEN: usize = 64;
799 let data = [1_u8; BUF_LEN];
800
801 let mut slice = data.as_ref();
802 let mut take = Read::take(&mut slice, 32);
803
804 let mut v = Vec::new();
805 let read = take.read_to_end(&mut v).unwrap();
806 assert_eq!(read, 32);
807 assert_eq!(data[0..32], v[0..32]);
808 }
809
810 #[test]
811 fn cursor_fill_buf_past_end() {
812 let data = [1, 2, 3];
813 let mut cursor = Cursor::new(&data);
814 cursor.set_position(10);
815
816 let buf = cursor.fill_buf().unwrap();
817 assert!(buf.is_empty());
818 }
819
820 #[test]
821 fn cursor_write() {
822 let data = [0x78, 0x56, 0x34, 0x12];
823
824 let mut buf = [0_u8; 4];
825 let mut cursor = Cursor::new(&mut buf);
826 let amt = cursor.write(&data).unwrap();
827
828 assert_eq!(buf, data);
829 assert_eq!(amt, 4);
830 }
831
832 #[test]
833 fn cursor_offset_write() {
834 let data = [0x78, 0x56, 0x34, 0x12];
835
836 let mut buf = [0_u8; 4];
837 let mut cursor = Cursor::new(&mut buf);
838 cursor.set_position(2);
839 let amt = cursor.write(&data).unwrap();
840
841 assert_eq!(buf, [0, 0, 0x78, 0x56]);
842 assert_eq!(amt, 2);
843 }
844
845 #[test]
846 fn cursor_consume_past_end() {
847 let data = [1, 2, 3];
848 let mut cursor = Cursor::new(&data);
849 cursor.set_position(10);
850
851 cursor.consume(5);
852 assert_eq!(cursor.position(), 15);
853 }
854
855 struct TestData(u32);
857
858 impl encoding::Encodable for TestData {
859 type Encoder<'e>
860 = ArrayEncoder<4>
861 where
862 Self: 'e;
863
864 fn encoder(&self) -> Self::Encoder<'_> {
865 ArrayEncoder::without_length_prefix(self.0.to_le_bytes())
866 }
867 }
868
869 #[test]
870 fn encode_io_writer() {
871 let data = TestData(0x1234_5678);
872
873 let mut buf = [0_u8; 4];
874 encode_to_writer(&data, buf.as_mut_slice()).unwrap();
875
876 assert_eq!(buf, [0x78, 0x56, 0x34, 0x12]);
877 }
878
879 #[derive(Debug, PartialEq)]
880 struct TestArray([u8; 4]);
881
882 impl Decodable for TestArray {
883 type Decoder = TestArrayDecoder;
884 fn decoder() -> Self::Decoder {
885 TestArrayDecoder { inner: ArrayDecoder::new() }
886 }
887 }
888
889 struct TestArrayDecoder {
890 inner: ArrayDecoder<4>,
891 }
892
893 impl Decoder for TestArrayDecoder {
894 type Output = TestArray;
895 type Error = UnexpectedEofError;
896
897 fn push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result<bool, Self::Error> {
898 self.inner.push_bytes(bytes)
899 }
900
901 fn end(self) -> core::result::Result<Self::Output, Self::Error> {
902 self.inner.end().map(TestArray)
903 }
904
905 fn read_limit(&self) -> usize {
906 self.inner.read_limit()
907 }
908 }
909
910 #[test]
911 fn decode_from_read_success() {
912 let data = [1, 2, 3, 4];
913 let cursor = Cursor::new(&data);
914 let result: core::result::Result<TestArray, _> = decode_from_read(cursor);
915 assert!(result.is_ok());
916 let decoded = result.unwrap();
917 assert_eq!(decoded.0, [1, 2, 3, 4]);
918 }
919
920 #[test]
921 fn decode_from_read_unexpected_eof() {
922 let data = [1, 2, 3];
923 let cursor = Cursor::new(&data);
924 let result: core::result::Result<TestArray, _> = decode_from_read(cursor);
925 assert!(matches!(result, Err(ReadError::Decode(_))));
926 }
927
928 #[test]
929 fn decode_from_read_trait_object() {
930 let data = [1, 2, 3, 4];
931 let mut cursor = Cursor::new(&data);
932 let reader: &mut dyn BufRead = &mut cursor;
934 let result: core::result::Result<TestArray, _> = decode_from_read(reader);
935 assert!(result.is_ok());
936 let decoded = result.unwrap();
937 assert_eq!(decoded.0, [1, 2, 3, 4]);
938 }
939
940 #[test]
941 #[cfg(feature = "alloc")]
942 fn decode_from_read_by_reference() {
943 use crate::alloc::vec::Vec;
944
945 let data = [1, 2, 3, 4];
946 let mut cursor = Cursor::new(&data);
947 let result: core::result::Result<TestArray, _> = decode_from_read(&mut cursor);
949 assert!(result.is_ok());
950 let decoded = result.unwrap();
951 assert_eq!(decoded.0, [1, 2, 3, 4]);
952
953 let mut buf = Vec::new();
954 let _ = cursor.read_to_limit(&mut buf, 100);
955 }
956
957 #[test]
958 fn decode_from_read_unbuffered_success() {
959 let data = [1, 2, 3, 4];
960 let cursor = Cursor::new(&data);
961 let result: core::result::Result<TestArray, _> = decode_from_read_unbuffered(cursor);
962 assert!(result.is_ok());
963 let decoded = result.unwrap();
964 assert_eq!(decoded.0, [1, 2, 3, 4]);
965 }
966
967 #[test]
968 fn decode_from_read_unbuffered_unexpected_eof() {
969 let data = [1, 2, 3];
970 let cursor = Cursor::new(&data);
971 let result: core::result::Result<TestArray, _> = decode_from_read_unbuffered(cursor);
972 assert!(matches!(result, Err(ReadError::Decode(_))));
973 }
974
975 #[test]
976 fn decode_from_read_unbuffered_empty() {
977 let data = [];
978 let cursor = Cursor::new(&data);
979 let result: core::result::Result<TestArray, _> = decode_from_read_unbuffered(cursor);
980 assert!(matches!(result, Err(ReadError::Decode(_))));
981 }
982
983 #[test]
984 fn decode_from_read_unbuffered_extra_data() {
985 let data = [1, 2, 3, 4, 5, 6];
986 let cursor = Cursor::new(&data);
987 let result: core::result::Result<TestArray, _> = decode_from_read_unbuffered(cursor);
988 assert!(result.is_ok());
989 let decoded = result.unwrap();
990 assert_eq!(decoded.0, [1, 2, 3, 4]);
991 }
992}