1use super::PolicyValidationContext;
6use super::arrays::SimpleArrayView;
7use super::parser::{PolicyCursor, PolicyData, PolicyOffset};
8use crate::policy::{Counted, Parse, Validate};
9use hashbrown::hash_table::HashTable;
10use std::fmt::Debug;
11use std::hash::{DefaultHasher, Hash, Hasher};
12use std::marker::PhantomData;
13use zerocopy::FromBytes;
14
15pub trait HasMetadata {
21 type Metadata: FromBytes + Sized;
23}
24
25pub trait Walk {
29 fn walk(policy_data: &PolicyData, offset: PolicyOffset) -> PolicyOffset;
33}
34
35#[derive(Debug, Clone, Copy)]
40pub struct View<T> {
41 phantom: PhantomData<T>,
42
43 start: PolicyOffset,
45
46 end: PolicyOffset,
48}
49
50impl<T> View<T> {
51 pub fn new(start: PolicyOffset, end: PolicyOffset) -> Self {
53 Self { phantom: PhantomData, start, end }
54 }
55
56 fn start(&self) -> PolicyOffset {
58 self.start
59 }
60}
61
62impl<T: Sized> View<T> {
63 pub fn at(start: PolicyOffset) -> Self {
67 let end = start + std::mem::size_of::<T>() as u32;
68 Self::new(start, end)
69 }
70}
71
72impl<T: FromBytes + Sized> View<T> {
73 pub fn read(&self, policy_data: &PolicyData) -> T {
80 debug_assert_eq!(self.end - self.start, std::mem::size_of::<T>() as u32);
81 let start = self.start as usize;
82 let end = self.end as usize;
83 T::read_from_bytes(&policy_data[start..end]).unwrap()
84 }
85}
86
87impl<T: HasMetadata> View<T> {
88 pub fn metadata(&self) -> View<T::Metadata> {
92 View::<T::Metadata>::at(self.start)
93 }
94
95 pub fn read_metadata(&self, policy_data: &PolicyData) -> T::Metadata {
97 self.metadata().read(policy_data)
98 }
99}
100
101impl<T: Parse> View<T> {
102 pub fn parse(&self, policy_data: &PolicyData) -> T {
108 let cursor = PolicyCursor::new_at(policy_data.clone(), self.start);
109 let (object, _) =
110 T::parse(cursor).map_err(Into::<anyhow::Error>::into).expect("policy should be valid");
111 object
112 }
113}
114
115impl<T: Validate + Parse> Validate for View<T> {
116 type Error = anyhow::Error;
117
118 fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
119 let object = self.parse(&context.data);
120 object.validate(context).map_err(Into::<anyhow::Error>::into)
121 }
122}
123
124#[derive(Debug, Clone, Copy)]
129pub struct ArrayDataView<D> {
130 phantom: PhantomData<D>,
131 start: PolicyOffset,
132 count: u32,
133}
134
135impl<D> ArrayDataView<D> {
136 pub fn new(start: PolicyOffset, count: u32) -> Self {
138 Self { phantom: PhantomData, start, count }
139 }
140
141 pub fn iter(self, policy_data: &PolicyData) -> ArrayDataViewIter<D> {
148 ArrayDataViewIter::new(policy_data.clone(), self.start, self.count)
149 }
150}
151
152pub struct ArrayDataViewIter<D> {
157 phantom: PhantomData<D>,
158 policy_data: PolicyData,
159 offset: PolicyOffset,
160 remaining: u32,
161}
162
163impl<T> ArrayDataViewIter<T> {
164 pub(crate) fn new(policy_data: PolicyData, offset: PolicyOffset, remaining: u32) -> Self {
166 Self { phantom: PhantomData, policy_data, offset, remaining }
167 }
168}
169
170impl<D: Walk> std::iter::Iterator for ArrayDataViewIter<D> {
171 type Item = View<D>;
172
173 fn next(&mut self) -> Option<Self::Item> {
174 if self.remaining > 0 {
175 let start = self.offset;
176 self.offset = D::walk(&self.policy_data, start);
177 self.remaining -= 1;
178 Some(View::new(start, self.offset))
179 } else {
180 None
181 }
182 }
183}
184
185#[derive(Debug, Clone, Copy)]
190pub(crate) struct ArrayView<M, D> {
191 phantom: PhantomData<(M, D)>,
192 start: PolicyOffset,
193 count: u32,
194}
195
196impl<M, D> ArrayView<M, D> {
197 pub fn new(start: PolicyOffset, count: u32) -> Self {
199 Self { phantom: PhantomData, start, count }
200 }
201}
202
203impl<M: Sized, D> ArrayView<M, D> {
204 pub fn metadata(&self) -> View<M> {
206 View::<M>::at(self.start)
207 }
208
209 pub fn data(&self) -> ArrayDataView<D> {
211 ArrayDataView::new(self.metadata().end, self.count)
212 }
213}
214
215fn parse_array_data<D: Parse>(
216 cursor: PolicyCursor,
217 count: u32,
218) -> Result<PolicyCursor, anyhow::Error> {
219 let mut tail = cursor;
220 for _ in 0..count {
221 let (_, next) = D::parse(tail).map_err(Into::<anyhow::Error>::into)?;
222 tail = next;
223 }
224 Ok(tail)
225}
226
227impl<M: Counted + Parse + Sized, D: Parse> Parse for ArrayView<M, D> {
228 type Error = anyhow::Error;
231
232 fn parse(cursor: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
233 let start = cursor.offset();
234 let (metadata, cursor) = M::parse(cursor).map_err(Into::<anyhow::Error>::into)?;
235 let count = metadata.count();
236 let cursor = parse_array_data::<D>(cursor, count)?;
237 Ok((Self::new(start, count), cursor))
238 }
239}
240
241struct HashedArrayViewEntryIter<'a, D: HasMetadata> {
244 policy_data: &'a PolicyData,
245 limit: PolicyOffset,
246 metadata: D::Metadata,
247 offset: Option<PolicyOffset>,
248}
249
250impl<'a, D: HasMetadata + Walk> Iterator for HashedArrayViewEntryIter<'a, D>
251where
252 D::Metadata: Eq,
253{
254 type Item = View<D>;
255
256 fn next(&mut self) -> Option<Self::Item> {
257 if let Some(offset) = self.offset
258 && offset < self.limit
259 {
260 let element = View::<D>::at(offset);
261 let metadata = element.read_metadata(&self.policy_data);
262 if metadata == self.metadata {
263 self.offset = Some(D::walk(&self.policy_data, offset));
264 Some(element)
265 } else {
266 self.offset = None;
267 None
268 }
269 } else {
270 None
271 }
272 }
273}
274
275#[derive(Debug, Clone)]
280pub(crate) struct HashedArrayView<D: HasMetadata> {
281 phantom: PhantomData<D>,
282 index: HashTable<PolicyOffset>,
283 limit: PolicyOffset,
287}
288
289impl<D: HasMetadata> HashedArrayView<D>
290where
291 D::Metadata: Hash,
292{
293 fn metadata_hash(metadata: &D::Metadata) -> u64 {
294 let mut hasher = DefaultHasher::new();
295 metadata.hash(&mut hasher);
296 hasher.finish()
297 }
298}
299
300impl<D: Parse + HasMetadata + Walk> HashedArrayView<D>
301where
302 D::Metadata: Eq + PartialEq + Hash + Debug,
303{
304 pub fn find(&self, key: D::Metadata, policy_data: &PolicyData) -> Option<D> {
309 let key_hash = Self::metadata_hash(&key);
310 let offset = self.index.find(key_hash, |&offset| {
311 let element = View::<D>::at(offset);
312 key == element.read_metadata(policy_data)
313 })?;
314 let element = View::<D>::at(*offset);
315 Some(element.parse(policy_data))
316 }
317
318 pub(super) fn iterate(
321 &self,
322 key: D::Metadata,
323 policy_data: &PolicyData,
324 ) -> impl Iterator<Item = D> {
325 let key_hash = Self::metadata_hash(&key);
326 let offset = self.index.find(key_hash, |&offset| {
327 let element = View::<D>::at(offset);
328 key == element.read_metadata(policy_data)
329 });
330 (HashedArrayViewEntryIter {
331 policy_data: policy_data,
332 limit: self.limit,
333 metadata: key,
334 offset: offset.cloned(),
335 })
336 .map(|element| element.parse(policy_data))
337 }
338
339 pub(super) fn iterate_all(&self, policy_data: &PolicyData) -> impl Iterator<Item = View<D>> {
341 self.index
342 .iter()
343 .map(|offset| {
344 let element = View::<D>::at(*offset);
345 HashedArrayViewEntryIter {
346 policy_data: policy_data,
347 limit: self.limit,
348 metadata: element.read_metadata(policy_data),
349 offset: Some(*offset),
350 }
351 })
352 .flatten()
353 }
354}
355
356impl<D: Parse + HasMetadata + Walk> Parse for HashedArrayView<D>
357where
358 D::Metadata: Eq + Debug + PartialEq + Parse + Hash,
359{
360 type Error = anyhow::Error;
361
362 fn parse(cursor: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
363 let (array_view, cursor) = SimpleArrayView::<D>::parse(cursor)?;
364
365 let mut index = HashTable::with_capacity(array_view.count as usize);
367
368 let limit = cursor.offset();
370
371 for view in array_view.data().iter(cursor.data()) {
374 let metadata = view.read_metadata(cursor.data());
375
376 index
377 .entry(
378 Self::metadata_hash(&metadata),
379 |&offset| {
380 let element = View::<D>::at(offset);
381 metadata == element.read_metadata(cursor.data())
382 },
383 |&offset| {
384 let element = View::<D>::at(offset);
385 Self::metadata_hash(&element.read_metadata(cursor.data()))
386 },
387 )
388 .or_insert(view.start());
389 }
390
391 Ok((Self { phantom: PhantomData, index, limit }, cursor))
392 }
393}
394
395impl<D: Validate + Parse + HasMetadata + Walk> Validate for HashedArrayView<D>
396where
397 D::Metadata: Eq,
398{
399 type Error = anyhow::Error;
400
401 fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
402 let policy_data = context.data.clone();
403 for element in self
404 .index
405 .iter()
406 .map(|offset| {
407 let element = View::<D>::at(*offset);
408 HashedArrayViewEntryIter::<D> {
409 policy_data: &policy_data,
410 limit: self.limit,
411 metadata: element.read_metadata(&policy_data),
412 offset: Some(*offset),
413 }
414 })
415 .flatten()
416 {
417 element.validate(context)?;
418 }
419
420 Ok(())
421 }
422}