1use std::io;
8
9use crate::IterReadItem;
10
11
12macro_rules! impl_byte {
13 ($el_ty:ty, $($deref:tt)*) => {
14 impl<'a> IterReadItem for $el_ty {
15 impl_byte!(@inner [$($deref)*] []);
16 }
17
18 impl<'a, E> IterReadItem for Result<$el_ty, E> where io::Error: From<E> {
19 impl_byte!(@inner [$($deref)*] [?]);
20 }
21 };
22 (@inner [$($deref:tt)*] [$($try:tt)*]) => {
23 type Buffer = ();
24
25 fn read<I: Iterator<Item=Self>>(target: &mut [u8], it: &mut I,
26 _: &mut ()) -> io::Result<usize> {
27 let mut len = 0;
28 for (slot, elt) in target.iter_mut().zip(it) {
29 *slot = $($deref)* elt $($try)*;
30 len += 1;
31 }
32 Ok(len)
33 }
34 }
35}
36
37pub struct Buf<T> {
38 bytes: T,
39 consumed: usize,
40}
41
42macro_rules! impl_buf_default {
43 ($ty:ty) => {
44 impl<'a> Default for Buf<$ty> {
45 fn default() -> Self {
46 Buf { bytes: Default::default(), consumed: 0 }
47 }
48 }
49 }
50}
51
52impl_buf_default!(&'a [u8]);
53impl_buf_default!(Vec<u8>);
54
55impl<const N: usize> Default for Buf<[u8; N]> {
56 fn default() -> Self {
57 Buf { bytes: [0; N], consumed: N }
60 }
61}
62
63macro_rules! impl_slice_like {
64 ($el_ty:ty [$($const:tt)*], $buf_ty:ty, $conv:ident) => {
65 impl<'a, $($const)*> IterReadItem for $el_ty {
66 impl_slice_like!(@inner $buf_ty, $conv, buf:
67 Some(v) => {
68 *buf = Buf { bytes: v.$conv(), consumed: 0 };
69 });
70 }
71
72 impl<'a, E, $($const)*> IterReadItem for Result<$el_ty, E> where io::Error: From<E> {
73 impl_slice_like!(@inner $buf_ty, $conv, buf:
74 Some(Ok(v)) => {
75 *buf = Buf { bytes: v.$conv(), consumed: 0 };
76 }
77 Some(Err(err)) => {
78 *buf = Buf::default();
79 return Err(err.into());
80 });
81 }
82 };
83 (@inner $buf_ty:ty, $conv:ident, $buf:ident : $($match:tt)+) => {
84 type Buffer = Buf<$buf_ty>;
85
86 fn read<I: Iterator<Item=Self>>(target: &mut [u8], it: &mut I,
87 $buf: &mut Self::Buffer) -> io::Result<usize> {
88 while $buf.consumed == $buf.bytes.len() {
89 match it.next() {
90 $($match)+
91 None => {
92 *$buf = Buf::default();
93 return Ok(0);
94 }
95 }
96 }
97 let mut len = 0;
98 for (slot, elt) in target.iter_mut().zip(&$buf.bytes[$buf.consumed..]) {
99 *slot = *elt;
100 len += 1;
101 }
102 $buf.consumed += len;
103 Ok(len)
104 }
105 }
106}
107
108impl_byte!(u8, );
109impl_byte!(&'a u8, *);
110
111impl_slice_like!(&'a [u8] [], &'a [u8], into);
112impl_slice_like!(&'a Vec<u8> [], &'a [u8], as_slice);
113impl_slice_like!(Vec<u8> [], Vec<u8>, into);
114impl_slice_like!([u8; N] [const N: usize], [u8; N], into);
115impl_slice_like!(&'a [u8; N] [const N: usize], &'a [u8], as_slice);
116
117impl_slice_like!(&'a str [], &'a [u8], as_bytes);
118impl_slice_like!(&'a String [], &'a [u8], as_bytes);
119impl_slice_like!(String [], Vec<u8>, into_bytes);