1use crate::Session;
7use crate::byte_machine::{Decoder, Step};
8use crate::bytes::Form;
9use crate::error::{Error, ErrorKind, ReadFailure, Syntax};
10use crate::source::{Location, Source};
11use structured_asn1::Span;
12use structured_asn1::memory::{Execution, MemoryError, OwnedVec, Work};
13use structured_asn1::range::Window;
14
15pub use structured_asn1::range::{RangeSource, ReadError, Slice, Stamp};
16
17#[derive(Debug)]
19pub enum InputError<E> {
20 Resource {
22 location: Location,
24 cause: MemoryError,
26 },
27 Changed {
30 location: Location,
32 },
33 Contract {
35 location: Location,
37 },
38 Cause {
40 location: Location,
42 cause: E,
44 },
45}
46
47pub struct RangeReader<'q, S: RangeSource> {
51 session: &'q Session,
52 domain: Source,
53 window: Window<'q, S>,
54}
55
56impl<'q, S: RangeSource> RangeReader<'q, S> {
57 pub fn new<W: Work>(
60 source: &'q S,
61 session: &'q Session,
62 operation: &'q W,
63 ) -> Result<Self, InputError<S::Error>> {
64 Self::in_source(source, session, operation, Source::File)
65 }
66
67 pub(crate) fn in_source<W: Work>(
68 source: &'q S,
69 session: &'q Session,
70 operation: &'q W,
71 domain: Source,
72 ) -> Result<Self, InputError<S::Error>> {
73 let stamp = source.stamp();
74 Self::window(
75 source,
76 session,
77 operation,
78 domain,
79 stamp,
80 Span {
81 start: 0,
82 length: stamp.length,
83 },
84 )
85 }
86
87 pub(crate) fn in_region<W: Work>(
88 source: &'q S,
89 session: &'q Session,
90 operation: &'q W,
91 domain: Source,
92 bounds: Span,
93 ) -> Result<Self, InputError<S::Error>> {
94 Self::window(source, session, operation, domain, source.stamp(), bounds)
95 }
96
97 fn window<W: Work>(
98 source: &'q S,
99 session: &'q Session,
100 operation: &'q W,
101 domain: Source,
102 stamp: Stamp<S::Document, S::Generation>,
103 bounds: Span,
104 ) -> Result<Self, InputError<S::Error>> {
105 let window = Window::new(source, stamp, bounds, session.query(operation))
106 .map_err(|error| located(domain, error))?;
107 Ok(Self {
108 session,
109 domain,
110 window,
111 })
112 }
113
114 #[must_use]
116 pub fn stamp(&self) -> Stamp<S::Document, S::Generation> {
117 self.window.stamp()
118 }
119
120 #[must_use]
122 pub fn execution(&self) -> Execution<'q> {
123 self.window.execution()
124 }
125
126 pub(crate) fn session(&self) -> &'q Session {
127 self.session
128 }
129
130 pub(crate) fn location(&self, start: u64, length: u64) -> Location {
131 Location::new(self.domain, start, length).expect("bounded original-domain range")
132 }
133
134 pub(crate) fn fork(&self) -> Result<Self, InputError<S::Error>> {
138 Ok(Self {
139 session: self.session,
140 domain: self.domain,
141 window: self
142 .window
143 .fork()
144 .map_err(|error| located(self.domain, error))?,
145 })
146 }
147
148 pub async fn byte_at(&mut self, offset: u64) -> Result<Option<u8>, InputError<S::Error>> {
154 self.window
155 .byte_at(offset)
156 .await
157 .map_err(|error| located(self.domain, error))
158 }
159
160 pub(crate) async fn chunk_at(
161 &mut self,
162 offset: u64,
163 end: u64,
164 ) -> Result<&[u8], InputError<S::Error>> {
165 let domain = self.domain;
166 self.window
167 .chunk_at(offset, end)
168 .await
169 .map_err(|error| located(domain, error))
170 }
171
172 pub async fn decode_bytes(
177 &mut self,
178 body: Span,
179 form: Form,
180 ) -> Result<OwnedVec<u8, Execution<'q>>, ReadFailure<S::Error>> {
181 self.decode_bytes_limit(body, form, usize::MAX).await
182 }
183
184 pub(crate) async fn decode_bytes_limit(
185 &mut self,
186 body: Span,
187 form: Form,
188 maximum: usize,
189 ) -> Result<OwnedVec<u8, Execution<'q>>, ReadFailure<S::Error>> {
190 let bounds = self.window.bounds();
191 let enclosure = self.location(bounds.start, bounds.length);
192 self.check(enclosure)?;
193 let Some(end) = body.start.checked_add(body.length) else {
194 return Err(Error {
195 kind: ErrorKind::Foreign,
196 location: enclosure,
197 }
198 .into());
199 };
200 if body.start < bounds.start || end > bounds.end() {
201 return Err(Error {
202 kind: ErrorKind::Foreign,
203 location: enclosure,
204 }
205 .into());
206 }
207 let mut output = self.execution().vector();
208 let mut decoder = Decoder::new(form);
209 let mut at = body.start;
210 loop {
211 let input = if at < end {
212 self.byte_at(at).await?
213 } else {
214 None
215 };
216 match decoder.step(input) {
217 Step::More => {
218 debug_assert!(input.is_some());
219 at += 1;
220 }
221 Step::Byte { value, consumed } => {
222 if output.len() == maximum {
223 return Err(Error {
224 kind: ErrorKind::Syntax(Syntax::String),
225 location: self.location(at, 0),
226 }
227 .into());
228 }
229 if consumed {
230 at += 1;
231 }
232 output.try_push(value).map_err(|cause| Error {
233 kind: ErrorKind::Resource(cause),
234 location: self.location(at, 0),
235 })?;
236 }
237 Step::End => {
238 self.check(self.location(at, 0))?;
239 return Ok(output);
240 }
241 Step::Malformed => {
242 if input.is_some() {
243 at += 1;
244 }
245 return Err(Error {
246 kind: ErrorKind::Syntax(match form {
247 Form::Name => Syntax::Name,
248 Form::Literal | Form::Hexadecimal => Syntax::String,
249 }),
250 location: self.location(at, 0),
251 }
252 .into());
253 }
254 }
255 }
256 }
257
258 pub(crate) fn check(&self, location: Location) -> Result<(), InputError<S::Error>> {
259 debug_assert_eq!(location.source(), self.domain);
260 self.window
261 .check(location.span())
262 .map_err(|error| located(self.domain, error))
263 }
264}
265
266fn located<E>(domain: Source, error: structured_asn1::range::InputError<E>) -> InputError<E> {
267 use structured_asn1::range::InputError as RangeError;
268 let location = |range: Span| {
269 Location::new(domain, range.start, range.length).expect("bounded source range")
270 };
271 match error {
272 RangeError::Resource { range, cause } => InputError::Resource {
273 location: location(range),
274 cause,
275 },
276 RangeError::Changed { range } => InputError::Changed {
277 location: location(range),
278 },
279 RangeError::Contract { range } => InputError::Contract {
280 location: Location::new(domain, range.start, 0).expect("original invalid-range point"),
281 },
282 RangeError::Cause { range, cause } => InputError::Cause {
283 location: location(range),
284 cause,
285 },
286 }
287}