1use crate::cursor::bounded_len;
5
6use super::error::SourceLocation;
7use super::probe::{ParseError, ParseErrorKind};
8use super::space::SpaceId;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct BoundedCount(usize);
13
14impl BoundedCount {
15 pub fn get(self) -> usize {
17 self.0
18 }
19}
20
21#[derive(Debug, Clone, Copy)]
23pub struct View<'a> {
24 bytes: &'a [u8],
25 space: SpaceId,
26 start: usize,
27 end: usize,
28 position: usize,
29}
30
31impl<'a> View<'a> {
32 pub(crate) fn over_space(bytes: &'a [u8], space: SpaceId) -> View<'a> {
34 View {
35 bytes,
36 space,
37 start: 0,
38 end: bytes.len(),
39 position: 0,
40 }
41 }
42
43 pub(crate) fn space(self) -> SpaceId {
45 self.space
46 }
47
48 pub fn position(self) -> usize {
50 self.position
51 }
52
53 pub fn start(self) -> usize {
55 self.start
56 }
57
58 pub fn end(self) -> usize {
60 self.end
61 }
62
63 pub fn remaining(self) -> usize {
65 self.end.saturating_sub(self.position)
66 }
67
68 pub fn location(self) -> SourceLocation {
70 SourceLocation {
71 space: self.space,
72 offset: self.position as u64,
73 }
74 }
75
76 pub fn location_at(self, offset: usize) -> SourceLocation {
78 SourceLocation {
79 space: self.space,
80 offset: offset as u64,
81 }
82 }
83
84 pub fn window(self) -> &'a [u8] {
86 self.bytes.get(self.start..self.end).unwrap_or_default()
87 }
88
89 pub fn take(&mut self, count: usize) -> Option<&'a [u8]> {
91 let end = self.position.checked_add(count)?;
92 if end > self.end {
93 return None;
94 }
95 let bytes = self.bytes.get(self.position..end)?;
96 self.position = end;
97 Some(bytes)
98 }
99
100 pub fn array<const N: usize>(&mut self) -> Option<[u8; N]> {
102 self.take(N)?.try_into().ok()
103 }
104
105 pub fn skip(&mut self, count: usize) -> Option<()> {
107 self.take(count).map(|_| ())
108 }
109
110 pub fn seek(&mut self, position: usize) -> Option<()> {
112 (self.start <= position && position <= self.end).then(|| self.position = position)
113 }
114
115 pub fn u8(&mut self) -> Option<u8> {
117 self.array::<1>().map(|[value]| value)
118 }
119
120 pub fn child(self, start: usize, end: usize) -> Option<View<'a>> {
122 if self.start <= start && start <= end && end <= self.end {
123 Some(View {
124 bytes: self.bytes,
125 space: self.space,
126 start,
127 end,
128 position: start,
129 })
130 } else {
131 None
132 }
133 }
134
135 pub fn counted(self, count: u64, min_element_size: usize) -> Option<BoundedCount> {
137 bounded_len(count, min_element_size, self.remaining()).map(BoundedCount)
138 }
139
140 fn eof(self, needed: u64) -> ParseError {
142 ParseError {
143 location: self.location(),
144 kind: ParseErrorKind::UnexpectedEof {
145 needed,
146 remaining: self.remaining() as u64,
147 },
148 operation: "required_read",
149 }
150 }
151
152 pub fn req_take(&mut self, count: usize) -> Result<&'a [u8], ParseError> {
154 match self.take(count) {
155 Some(bytes) => Ok(bytes),
156 None => Err(self.eof(count as u64)),
157 }
158 }
159
160 pub fn req_u8(&mut self) -> Result<u8, ParseError> {
162 match self.u8() {
163 Some(value) => Ok(value),
164 None => Err(self.eof(1)),
165 }
166 }
167}
168
169macro_rules! view_readers {
170 ($(($probe:ident, $req:ident, $ty:ty, $conv:ident, $size:literal)),* $(,)?) => {
171 impl View<'_> {
172 $(
173 #[doc = concat!("Probe read of a `", stringify!($ty), "` via `", stringify!($conv), "`.")]
174 pub fn $probe(&mut self) -> Option<$ty> {
175 self.array::<$size>().map(<$ty>::$conv)
176 }
177
178 #[doc = concat!("Required-read mirror of [`View::", stringify!($probe), "`].")]
179 pub fn $req(&mut self) -> Result<$ty, ParseError> {
180 match self.array::<$size>() {
181 Some(bytes) => Ok(<$ty>::$conv(bytes)),
182 None => Err(self.eof($size)),
183 }
184 }
185 )*
186 }
187 };
188}
189
190view_readers!(
191 (u16_le, req_u16_le, u16, from_le_bytes, 2),
192 (i16_le, req_i16_le, i16, from_le_bytes, 2),
193 (u32_le, req_u32_le, u32, from_le_bytes, 4),
194 (i32_le, req_i32_le, i32, from_le_bytes, 4),
195 (u64_le, req_u64_le, u64, from_le_bytes, 8),
196 (i64_le, req_i64_le, i64, from_le_bytes, 8),
197 (f32_le, req_f32_le, f32, from_le_bytes, 4),
198 (f64_le, req_f64_le, f64, from_le_bytes, 8),
199 (u16_be, req_u16_be, u16, from_be_bytes, 2),
200 (u32_be, req_u32_be, u32, from_be_bytes, 4),
201 (u64_be, req_u64_be, u64, from_be_bytes, 8),
202 (f64_be, req_f64_be, f64, from_be_bytes, 8),
203);