1use super::Segment;
2use crate::{
3 error::{Error, Result},
4 marker::Integer,
5 Endidness,
6};
7use core::convert::TryFrom;
8pub type DataSegment<'s> = Segment<'s, u8>;
10
11macro_rules! make_num_method {
12 ($type:ty, $name:ident, $method:ident, $($doc:literal),+) => {
13 $(#[doc = $doc])+
14 pub fn $name(&self) -> Result<$type> {
15 self.$method::<$type>()
16 }
17 };
18}
19macro_rules! make_num_method_with_offset {
20 ($type:ty, $name:ident, $method:ident, $($doc:literal),+) => {
21 $(#[doc = $doc])+
22 pub fn $name(&self, offset: usize) -> Result<$type> {
23 self.$method::<$type>(offset)
24 }
25 };
26}
27
28impl<'s> DataSegment<'s> {
29 #[inline]
33 pub fn with_endidness(data: &'s [u8], endidness: Endidness) -> Self {
34 Self::new_full(data, 0, 0, endidness)
35 }
36
37 #[inline]
41 pub fn with_offset_and_endidness(
42 data: &'s [u8],
43 initial_offset: usize,
44 endidness: Endidness,
45 ) -> Self {
46 Self::new_full(data, initial_offset, 0, endidness)
47 }
48
49 #[inline]
50 pub fn endidness(&self) -> Endidness {
54 self.endidness
55 }
56
57 pub fn next_bytes(&self, buf: &mut [u8]) -> Result<()> {
62 for i in 0..buf.len() {
64 buf[i] = self.next_u8()?;
65 }
66 Ok(())
67 }
68
69 fn int_at_pos<N: Integer>(&self, pos: usize) -> Result<N> {
70 self.validate_pos(pos, N::WIDTH - 1)?;
71 Ok(N::with_endidness(
72 &self.data[pos..pos + N::WIDTH],
73 self.endidness,
74 ))
75 }
76
77 pub fn int_at<N: Integer>(&self, offset: usize) -> Result<N> {
83 self.validate_offset(offset, N::WIDTH - 1)?;
84 Ok(N::with_endidness(
85 &self[offset..offset + N::WIDTH],
86 self.endidness,
87 ))
88 }
89
90 #[inline]
91 pub fn u8_at(&self, offset: usize) -> Result<u8> {
95 self.item_at(offset)
96 }
97 make_num_method_with_offset! {u16, u16_at, int_at,
98 "See the documentation for [`Segment::int_at`].\n\n",
99 "Note: Only available if the [`Segment`]'s I is `u8`."}
100
101 make_num_method_with_offset! {u32, u32_at, int_at,
102 "See the documentation for [`Segment::int_at`].\n\n",
103 "Note: Only available if the [`Segment`]'s I is `u8`."}
104
105 make_num_method_with_offset! {u64, u64_at, int_at,
106 "See the documentation for [`Segment::int_at`].\n\n",
107 "Note: Only available if the [`Segment`]'s I is `u8`."}
108
109 make_num_method_with_offset! {u128, u128_at, int_at,
110 "See the documentation for [`Segment::int_at`].\n\n",
111 "Note: Only available if the [`Segment`]'s I is `u8`."}
112
113 make_num_method_with_offset! {i8, i8_at, int_at,
114 "See the documentation for [`Segment::int_at`].\n\n",
115 "Note: Only available if the [`Segment`]'s I is `u8`."}
116
117 make_num_method_with_offset! {i16, i16_at, int_at,
118 "See the documentation for [`Segment::int_at`].\n\n",
119 "Note: Only available if the [`Segment`]'s I is `u8`."}
120
121 make_num_method_with_offset! {i32, i32_at, int_at,
122 "See the documentation for [`Segment::int_at`].\n\n",
123 "Note: Only available if the [`Segment`]'s I is `u8`."}
124
125 make_num_method_with_offset! {i64, i64_at, int_at,
126 "See the documentation for [`Segment::int_at`].\n\n",
127 "Note: Only available if the [`Segment`]'s I is `u8`."}
128
129 make_num_method_with_offset! {i128, i128_at, int_at,
130 "See the documentation for [`Segment::int_at`].\n\n",
131 "Note: Only available if the [`Segment`]'s I is `u8`."}
132
133 #[inline]
139 pub fn current_int<N: Integer>(&self) -> Result<N> {
140 self.int_at(self.current_offset())
141 }
142
143 make_num_method! {u8, current_u8, current_int,
144 "See the documentation for [`Segment::current_int`].\n\n",
145 "Note: Only available if the [`Segment`]'s I is `u8`."}
146
147 make_num_method! {u16, current_u16, current_int,
148 "See the documentation for [`Segment::current_int`].\n\n",
149 "Note: Only available if the [`Segment`]'s I is `u8`."}
150
151 make_num_method! {u32, current_u32, current_int,
152 "See the documentation for [`Segment::current_int`].\n\n",
153 "Note: Only available if the [`Segment`]'s I is `u8`."}
154
155 make_num_method! {u64, current_u64, current_int,
156 "See the documentation for [`Segment::current_int`].\n\n",
157 "Note: Only available if the [`Segment`]'s I is `u8`."}
158
159 make_num_method! {u128, current_u128, current_int,
160 "See the documentation for [`Segment::current_int`].\n\n",
161 "Note: Only available if the [`Segment`]'s I is `u8`."}
162
163 make_num_method! {i8, current_i8, current_int,
164 "See the documentation for [`Segment::current_int`].\n\n",
165 "Note: Only available if the [`Segment`]'s I is `u8`."}
166
167 make_num_method! {i16, current_i16, current_int,
168 "See the documentation for [`Segment::current_int`].\n\n",
169 "Note: Only available if the [`Segment`]'s I is `u8`."}
170
171 make_num_method! {i32, current_i32, current_int,
172 "See the documentation for [`Segment::current_int`].\n\n",
173 "Note: Only available if the [`Segment`]'s I is `u8`."}
174
175 make_num_method! {i64, current_i64, current_int,
176 "See the documentation for [`Segment::current_int`].\n\n",
177 "Note: Only available if the [`Segment`]'s I is `u8`."}
178
179 make_num_method! {i128, current_i128, current_int,
180 "See the documentation for [`Segment::current_int`].\n\n",
181 "Note: Only available if the [`Segment`]'s I is `u8`."}
182
183 pub fn peek_int<N: Integer>(&self) -> Result<N> {
190 let pos = self.adj_pos(N::WIDTH as i128)?;
191 self.int_at(self.pos_to_offset(pos))
192 }
193
194 make_num_method! {u8, peek_u8, peek_int,
195 "See the documentation for [`Segment::peek_int`].\n\n",
196 "Note: Only available if the [`Segment`]'s I is `u8`."}
197
198 make_num_method! {u16, peek_u16, peek_int,
199 "See the documentation for [`Segment::peek_int`].\n\n",
200 "Note: Only available if the [`Segment`]'s I is `u8`."}
201
202 make_num_method! {u32, peek_u32, peek_int,
203 "See the documentation for [`Segment::peek_int`].\n\n",
204 "Note: Only available if the [`Segment`]'s I is `u8`."}
205
206 make_num_method! {u64, peek_u64, peek_int,
207 "See the documentation for [`Segment::peek_int`].\n\n",
208 "Note: Only available if the [`Segment`]'s I is `u8`."}
209
210 make_num_method! {u128, peek_u128, peek_int,
211 "See the documentation for [`Segment::peek_int`].\n\n",
212 "Note: Only available if the [`Segment`]'s I is `u8`."}
213
214 make_num_method! {i8, peek_i8, peek_int,
215 "See the documentation for [`Segment::peek_int`].\n\n",
216 "Note: Only available if the [`Segment`]'s I is `u8`."}
217
218 make_num_method! {i16, peek_i16, peek_int,
219 "See the documentation for [`Segment::peek_int`].\n\n",
220 "Note: Only available if the [`Segment`]'s I is `u8`."}
221
222 make_num_method! {i32, peek_i32, peek_int,
223 "See the documentation for [`Segment::peek_int`].\n\n",
224 "Note: Only available if the [`Segment`]'s I is `u8`."}
225
226 make_num_method! {i64, peek_i64, peek_int,
227 "See the documentation for [`Segment::peek_int`].\n\n",
228 "Note: Only available if the [`Segment`]'s I is `u8`."}
229
230 make_num_method! {i128, peek_i128, peek_int,
231 "See the documentation for [`Segment::peek_int`].\n\n",
232 "Note: Only available if the [`Segment`]'s I is `u8`."}
233
234 pub fn next_int<N: Integer>(&self) -> Result<N> {
241 let pos = self.adj_pos(N::WIDTH as i128)?;
242 self.int_at(self.pos_to_offset(pos))
243 }
244
245 #[inline]
246 pub fn next_u8(&self) -> Result<u8> {
250 self.next_item()
251 }
252
253 make_num_method! {u16, next_u16, next_int,
254 "See the documentation for [`Segment::next_int`].\n\n",
255 "Note: Only available if the [`Segment`]'s I is `u8`."}
256
257 make_num_method! {u32, next_u32, next_int,
258 "See the documentation for [`Segment::next_int`].\n\n",
259 "Note: Only available if the [`Segment`]'s I is `u8`."}
260
261 make_num_method! {u64, next_u64, next_int,
262 "See the documentation for [`Segment::next_int`].\n\n",
263 "Note: Only available if the [`Segment`]'s I is `u8`."}
264
265 make_num_method! {u128, next_u128, next_int,
266 "See the documentation for [`Segment::next_int`].\n\n",
267 "Note: Only available if the [`Segment`]'s I is `u8`."}
268
269 make_num_method! {i8, next_i8, next_int,
270 "See the documentation for [`Segment::next_int`].\n\n",
271 "Note: Only available if the [`Segment`]'s I is `u8`."}
272
273 make_num_method! {i16, next_i16, next_int,
274 "See the documentation for [`Segment::next_int`].\n\n",
275 "Note: Only available if the [`Segment`]'s I is `u8`."}
276
277 make_num_method! {i32, next_i32, next_int,
278 "See the documentation for [`Segment::next_int`].\n\n",
279 "Note: Only available if the [`Segment`]'s I is `u8`."}
280
281 make_num_method! {i64, next_i64, next_int,
282 "See the documentation for [`Segment::next_int`].\n\n",
283 "Note: Only available if the [`Segment`]'s I is `u8`."}
284
285 make_num_method! {i128, next_i128, next_int,
286 "See the documentation for [`Segment::next_int`].\n\n",
287 "Note: Only available if the [`Segment`]'s I is `u8`."}
288}
289impl<'s> TryFrom<&DataSegment<'s>> for () {
290 type Error = Error;
291 fn try_from(_: &Segment<'s, u8>) -> Result<Self> {
292 Ok(())
293 }
294}
295impl<'s> TryFrom<&Segment<'s, u8>> for u8 {
296 type Error = Error;
297 fn try_from(segment: &Segment<'s, u8>) -> Result<Self> {
298 segment.next_item()
299 }
300}
301
302macro_rules! impl_try_from {
303 ($type:ty) => {
304 impl<'s> TryFrom<&Segment<'s, u8>> for $type {
305 type Error = Error;
306 fn try_from(segment: &Segment<'s, u8>) -> Result<Self> {
307 segment.next_int()
308 }
309 }
310 impl<'s, const N: usize> TryFrom<&Segment<'s, u8>> for [$type; N] {
311 type Error = Error;
312 fn try_from(segment: &Segment<'s, u8>) -> Result<Self> {
313 let pos = segment.adj_pos((<$type>::WIDTH * N) as i128)?;
314 let mut array = [0; N];
315 for i in 0..N {
316 array[i] = segment.int_at_pos(pos + (i * <$type>::WIDTH))?
317 }
318 Ok(array)
319 }
320 }
321 };
322}
323
324impl_try_from! { u16 }
325impl_try_from! { u32 }
326impl_try_from! { u64 }
327impl_try_from! { u128 }
328
329impl_try_from! { i8 }
330impl_try_from! { i16 }
331impl_try_from! { i32 }
332impl_try_from! { i64 }
333impl_try_from! { i128 }