1use core::marker::PhantomData;
4
5use crate::EpeeError;
6
7pub trait BytesLike<'encoding>: Sized {
9 type ExternallyTrackedLength: Sized + Copy;
14
15 fn len(&self, len: Self::ExternallyTrackedLength) -> usize;
17
18 fn read_bytes(
22 &mut self,
23 bytes: usize,
24 ) -> Result<(Self::ExternallyTrackedLength, Self), EpeeError>;
25
26 fn read_into_slice(&mut self, slice: &mut [u8]) -> Result<(), EpeeError>;
32
33 #[inline(always)]
35 fn read_byte(&mut self) -> Result<u8, EpeeError> {
36 let mut buf = [0; 1];
37 self.read_into_slice(&mut buf)?;
38 Ok(buf[0])
39 }
40
41 #[inline(always)]
43 fn advance<const N: usize>(&mut self) -> Result<(), EpeeError> {
44 self.read_bytes(N).map(|_| ())
45 }
46}
47
48impl<'encoding> BytesLike<'encoding> for &'encoding [u8] {
49 type ExternallyTrackedLength = ();
50
51 #[inline(always)]
52 fn len(&self, (): ()) -> usize {
53 <[u8]>::len(self)
54 }
55
56 #[inline(always)]
57 fn read_bytes(
58 &mut self,
59 bytes: usize,
60 ) -> Result<(Self::ExternallyTrackedLength, Self), EpeeError> {
61 if self.len() < bytes {
62 Err(EpeeError::Short(bytes))?;
63 }
64 let res = &self[.. bytes];
65 *self = &self[bytes ..];
66 Ok(((), res))
67 }
68
69 #[inline(always)]
70 fn read_into_slice(&mut self, slice: &mut [u8]) -> Result<(), EpeeError> {
71 slice.copy_from_slice(self.read_bytes(slice.len())?.1);
78 Ok(())
79 }
80}
81
82pub(crate) fn read_varint<'encoding>(
89 reader: &mut impl BytesLike<'encoding>,
90) -> Result<u64, EpeeError> {
91 let vi_start = reader.read_byte()?;
92
93 let len = match vi_start & 0b11 {
96 0 => 1,
97 1 => 2,
98 2 => 4,
99 3 => 8,
100 _ => unreachable!(),
101 };
102
103 let mut vi = u64::from(vi_start);
104 for i in 1 .. len {
105 vi |= u64::from(reader.read_byte()?) << (i * 8);
106 }
107 vi >>= 2;
108
109 Ok(vi)
110}
111
112pub struct String<'encoding, B: BytesLike<'encoding>> {
117 pub(crate) len: B::ExternallyTrackedLength,
118 pub(crate) bytes: B,
119 pub(crate) _encoding: PhantomData<&'encoding ()>,
120}
121
122impl<'encoding, B: BytesLike<'encoding>> String<'encoding, B> {
123 #[inline(always)]
125 pub fn is_empty(&self) -> bool {
126 self.bytes.len(self.len) == 0
127 }
128
129 #[inline(always)]
131 pub fn len(&self) -> usize {
132 self.bytes.len(self.len)
133 }
134
135 #[inline(always)]
137 pub fn consume(self) -> B {
138 self.bytes
139 }
140}
141
142#[inline(always)]
144pub(crate) fn read_str<'encoding, B: BytesLike<'encoding>>(
145 reader: &mut B,
146) -> Result<String<'encoding, B>, EpeeError> {
147 let len = usize::try_from(read_varint(reader)?).map_err(|_| EpeeError::Short(usize::MAX))?;
153 let (len, bytes) = reader.read_bytes(len)?;
154 Ok(String { len, bytes, _encoding: PhantomData })
155}