1use crate::Session;
4use crate::arena::{Arena, Kind, NodeId};
5use crate::bytes::Form;
6use crate::error::{Error, ErrorKind, Result, Syntax, Unsupported};
7use crate::range::Stamp;
8use crate::source::Location;
9use structured_asn1::memory::{Execution, Memory, Work};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum Type {
14 Null,
16 Boolean,
18 Integer,
20 Real,
22 Name,
24 String,
26 Array,
28 Dictionary,
30 Reference,
32}
33
34pub struct Value<'s, D, G> {
38 pub(crate) arena: Arena<Memory>,
39 pub(crate) root: NodeId,
40 pub(crate) session: &'s Session,
41 pub(crate) stamp: Stamp<D, G>,
42 pub(crate) end: u64,
43}
44
45impl<'s, D: Copy + Eq, G: Copy + Eq> Value<'s, D, G> {
46 #[must_use]
48 pub fn stamp(&self) -> Stamp<D, G> {
49 self.stamp
50 }
51
52 #[must_use]
54 pub fn end(&self) -> u64 {
55 self.end
56 }
57
58 #[must_use]
61 pub fn faults(&self) -> &[crate::error::Fault] {
62 &self.arena.faults
63 }
64
65 #[must_use]
67 pub fn root(&self) -> Object<'_, 's, D, G> {
68 Object {
69 owner: self,
70 node: self.root,
71 }
72 }
73}
74
75#[derive(Clone, Copy)]
78pub struct Object<'a, 's, D, G> {
79 pub(crate) owner: &'a Value<'s, D, G>,
80 pub(crate) node: NodeId,
81}
82
83impl<'a, 's, D: Copy + Eq, G: Copy + Eq> Object<'a, 's, D, G> {
84 #[must_use]
86 pub fn location(self) -> Location {
87 self.owner.arena.nodes[self.node.0].location
88 }
89
90 #[must_use]
92 pub fn kind(self) -> Type {
93 match self.owner.arena.nodes[self.node.0].kind {
94 Kind::Null => Type::Null,
95 Kind::Boolean(_) => Type::Boolean,
96 Kind::Integer(_) => Type::Integer,
97 Kind::Real { .. } => Type::Real,
98 Kind::Name(_) => Type::Name,
99 Kind::String(_) => Type::String,
100 Kind::Array(_) => Type::Array,
101 Kind::Dictionary(_, _) => Type::Dictionary,
102 Kind::Reference { .. } => Type::Reference,
103 }
104 }
105
106 #[must_use]
109 pub fn boolean(self) -> Option<bool> {
110 if let Kind::Boolean(value) = self.owner.arena.nodes[self.node.0].kind {
111 Some(value)
112 } else {
113 None
114 }
115 }
116
117 #[must_use]
121 pub fn string_body(self) -> Option<(Form, Location)> {
125 if let Kind::String(form) = self.owner.arena.nodes[self.node.0].kind {
126 let original = self.location();
127 debug_assert!(original.span().length >= 2);
128 Some((
129 form,
130 Location::new(
131 original.source(),
132 original.span().start + 1,
133 original.span().length - 2,
134 )
135 .expect("parsed string delimiters"),
136 ))
137 } else {
138 None
139 }
140 }
141
142 #[must_use]
145 pub fn reference(self) -> Option<(u64, u16)> {
146 if let Kind::Reference { number, generation } = self.owner.arena.nodes[self.node.0].kind {
147 Some((number, generation))
148 } else {
149 None
150 }
151 }
152
153 pub fn unsigned(self, operation: &impl Work) -> Result<u64> {
157 let location = self.location();
158 let work = self.owner.session.query(operation);
159 work.charge_work(1).map_err(|cause| Error {
160 kind: ErrorKind::Resource(cause),
161 location,
162 })?;
163 let Kind::Integer(value) = self.owner.arena.nodes[self.node.0].kind else {
164 return Err(Error {
165 kind: ErrorKind::Syntax(Syntax::Number),
166 location,
167 });
168 };
169 let Some(magnitude) = value.magnitude else {
170 return Err(Error {
171 kind: ErrorKind::Unsupported(Unsupported::NumericRange),
172 location,
173 });
174 };
175 if value.negative && magnitude != 0 {
176 return Err(Error {
177 kind: ErrorKind::Syntax(Syntax::Number),
178 location,
179 });
180 }
181 Ok(magnitude)
182 }
183
184 pub fn name_equals(self, expected: &[u8], operation: &impl Work) -> Result<bool> {
187 let location = self.location();
188 let work = self.owner.session.query(operation);
189 work.charge_work(1).map_err(|cause| Error {
190 kind: ErrorKind::Resource(cause),
191 location,
192 })?;
193 let Kind::Name(name) = self.owner.arena.nodes[self.node.0].kind else {
194 return Ok(false);
195 };
196 if name.length != expected.len() {
197 return Ok(false);
198 }
199 work.charge_work(name.length as u64)
200 .map_err(|cause| Error {
201 kind: ErrorKind::Resource(cause),
202 location,
203 })?;
204 Ok(&self.owner.arena.names[name.start..name.start + name.length] == expected)
205 }
206
207 pub fn get(self, key: &[u8], operation: &impl Work) -> Result<Option<Self>> {
212 let Kind::Dictionary(_, fields) = self.owner.arena.nodes[self.node.0].kind else {
213 return Err(Error {
214 kind: ErrorKind::Syntax(Syntax::Dictionary),
215 location: self.location(),
216 });
217 };
218 let work = self.owner.session.query(operation);
219 work.charge_work(1).map_err(|cause| Error {
220 kind: ErrorKind::Resource(cause),
221 location: self.location(),
222 })?;
223 Ok(
224 crate::dictionary::lookup(&self.owner.arena, fields, key, &work, self.location())?.map(
225 |node| Self {
226 owner: self.owner,
227 node,
228 },
229 ),
230 )
231 }
232
233 pub fn members<'q>(self, operation: &'q impl Work) -> Option<Members<'a, 's, 'q, D, G>>
238 where
239 's: 'q,
240 {
241 let (Kind::Array(children) | Kind::Dictionary(children, _)) =
242 self.owner.arena.nodes[self.node.0].kind
243 else {
244 return None;
245 };
246 Some(Members {
247 object: self,
248 next: children.first,
249 work: self.owner.session.query(operation),
250 })
251 }
252}
253
254pub struct Members<'a, 's, 'q, D, G> {
256 object: Object<'a, 's, D, G>,
257 next: Option<usize>,
258 work: Execution<'q>,
259}
260
261impl<'a, 's, D: Copy + Eq, G: Copy + Eq> Iterator for Members<'a, 's, '_, D, G> {
262 type Item = Result<Object<'a, 's, D, G>>;
263
264 fn next(&mut self) -> Option<Self::Item> {
265 let next = self.next?;
266 if let Err(cause) = self.work.charge_work(1) {
267 self.next = None;
268 return Some(Err(Error {
269 kind: ErrorKind::Resource(cause),
270 location: self.object.location(),
271 }));
272 }
273 let link = self.object.owner.arena.links[next];
274 self.next = link.next;
275 Some(Ok(Object {
276 owner: self.object.owner,
277 node: link.value,
278 }))
279 }
280}
281
282impl<D: Copy + Eq, G: Copy + Eq> core::iter::FusedIterator for Members<'_, '_, '_, D, G> {}