1use super::arrays::SimpleArrayView;
6use super::parser::{PolicyCursor, PolicyData, PolicyOffset};
7use super::{Counted, Parse, PolicyValidationContext, Validate};
8
9use hashbrown::hash_table::HashTable;
10use rapidhash::RapidHasher;
11use std::fmt::Debug;
12use std::hash::{Hash, Hasher};
13use std::marker::PhantomData;
14use zerocopy::{FromBytes, little_endian as le};
15
16pub trait HasMetadata {
22 type Metadata: FromBytes + Sized;
24}
25
26pub trait Walk {
30 fn walk(policy_data: &PolicyData, offset: PolicyOffset) -> PolicyOffset;
34}
35
36#[derive(Debug, Clone, Copy)]
41pub struct View<T> {
42 phantom: PhantomData<T>,
43
44 start: PolicyOffset,
46
47 end: PolicyOffset,
49}
50
51impl<T> View<T> {
52 pub fn new(start: PolicyOffset, end: PolicyOffset) -> Self {
54 Self { phantom: PhantomData, start, end }
55 }
56}
57
58impl<T: Sized> View<T> {
59 pub fn at(start: PolicyOffset) -> Self {
63 let end = start + std::mem::size_of::<T>() as u32;
64 Self::new(start, end)
65 }
66}
67
68impl<T: FromBytes + Sized> View<T> {
69 pub fn read(&self, policy_data: &PolicyData) -> T {
76 debug_assert_eq!(self.end - self.start, std::mem::size_of::<T>() as u32);
77 let start = self.start as usize;
78 let end = self.end as usize;
79 T::read_from_bytes(&policy_data[start..end]).unwrap()
80 }
81}
82
83impl<T: HasMetadata> View<T> {
84 pub fn metadata(&self) -> View<T::Metadata> {
88 View::<T::Metadata>::at(self.start)
89 }
90
91 pub fn read_metadata(&self, policy_data: &PolicyData) -> T::Metadata {
93 self.metadata().read(policy_data)
94 }
95}
96
97impl<T: Parse> View<T> {
98 pub fn parse(&self, policy_data: &PolicyData) -> T {
104 let cursor = PolicyCursor::new_at(policy_data, self.start);
105 let (object, _) =
106 T::parse(cursor).map_err(Into::<anyhow::Error>::into).expect("policy should be valid");
107 object
108 }
109}
110
111impl<T: Validate + Parse> Validate for View<T> {
112 type Error = anyhow::Error;
113
114 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error> {
115 let object = self.parse(&context.data);
116 object.validate(context).map_err(Into::<anyhow::Error>::into)
117 }
118}
119
120#[derive(Debug, Clone, Copy)]
125pub struct ArrayDataView<D> {
126 phantom: PhantomData<D>,
127 start: PolicyOffset,
128 count: u32,
129}
130
131impl<D> ArrayDataView<D> {
132 pub fn new(start: PolicyOffset, count: u32) -> Self {
134 Self { phantom: PhantomData, start, count }
135 }
136
137 pub fn iter(self, policy_data: &PolicyData) -> ArrayDataViewIter<D> {
144 ArrayDataViewIter::new(policy_data.clone(), self.start, self.count)
145 }
146}
147
148pub struct ArrayDataViewIter<D> {
153 phantom: PhantomData<D>,
154 policy_data: PolicyData,
155 offset: PolicyOffset,
156 remaining: u32,
157}
158
159impl<T> ArrayDataViewIter<T> {
160 fn new(policy_data: PolicyData, offset: PolicyOffset, remaining: u32) -> Self {
162 Self { phantom: PhantomData, policy_data, offset, remaining }
163 }
164}
165
166impl<D: Walk> std::iter::Iterator for ArrayDataViewIter<D> {
167 type Item = View<D>;
168
169 fn next(&mut self) -> Option<Self::Item> {
170 if self.remaining > 0 {
171 let start = self.offset;
172 self.offset = D::walk(&self.policy_data, start);
173 self.remaining -= 1;
174 Some(View::new(start, self.offset))
175 } else {
176 None
177 }
178 }
179}
180
181#[derive(Debug, Clone, Copy)]
186pub(super) struct ArrayView<M, D> {
187 phantom: PhantomData<(M, D)>,
188 start: PolicyOffset,
189 count: u32,
190}
191
192impl<M, D> ArrayView<M, D> {
193 pub fn new(start: PolicyOffset, count: u32) -> Self {
195 Self { phantom: PhantomData, start, count }
196 }
197}
198
199impl<M: Sized, D> ArrayView<M, D> {
200 pub fn metadata(&self) -> View<M> {
202 View::<M>::at(self.start)
203 }
204
205 pub fn data(&self) -> ArrayDataView<D> {
207 ArrayDataView::new(self.metadata().end, self.count)
208 }
209}
210
211fn parse_array_data<'a, D: Parse>(
212 cursor: PolicyCursor<'a>,
213 count: u32,
214) -> Result<PolicyCursor<'a>, anyhow::Error> {
215 let mut tail = cursor;
216 for _ in 0..count {
217 let (_, next) = D::parse(tail).map_err(Into::<anyhow::Error>::into)?;
218 tail = next;
219 }
220 Ok(tail)
221}
222
223impl<M: Counted + Parse + Sized, D: Parse> Parse for ArrayView<M, D> {
224 type Error = anyhow::Error;
227
228 fn parse<'a>(cursor: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error> {
229 let start = cursor.offset();
230 let (metadata, cursor) = M::parse(cursor).map_err(Into::<anyhow::Error>::into)?;
231 let count = metadata.count();
232 let cursor = parse_array_data::<D>(cursor, count)?;
233 Ok((Self::new(start, count), cursor))
234 }
235}
236
237pub(super) trait Hashable {
241 type Key: Parse + Hash + Eq;
242 type Value: Parse + Walk;
243
244 fn key(&self) -> &Self::Key;
246
247 fn values(&self) -> &SimpleArrayView<Self::Value>;
249}
250
251#[derive(Debug, Clone)]
253pub(super) struct CustomKeyHashedView<D: Hashable> {
254 index: HashTable<PolicyOffset>,
256 _phantom: PhantomData<D>,
257}
258
259impl<D: Hashable + Parse> CustomKeyHashedView<D> {
260 pub(super) fn find_all(
263 &self,
264 query_key: D::Key,
265 policy_data: &PolicyData,
266 ) -> impl Iterator<Item = D::Value> {
267 let key_offset = self.index.find(compute_hash(&query_key), |&key_offset| {
268 let cursor = PolicyCursor::new_at(policy_data, key_offset);
269 let (key, _) = D::Key::parse(cursor)
270 .map_err(Into::<anyhow::Error>::into)
271 .expect("policy should be valid");
272
273 key == query_key
274 });
275
276 key_offset.into_iter().flat_map(move |&key_offset| {
277 let cursor = PolicyCursor::new_at(policy_data, key_offset);
278 let (entry, _) = D::parse(cursor)
279 .map_err(Into::<anyhow::Error>::into)
280 .expect("policy should be valid");
281
282 entry.values().data().iter(policy_data).map(move |v| v.parse(policy_data))
283 })
284 }
285
286 pub(super) fn iter<'a>(
287 &'a self,
288 policy_data: &'a PolicyData,
289 ) -> impl Iterator<Item = Result<D, anyhow::Error>> + 'a {
290 self.index.iter().map(move |&offset| {
291 let cursor = PolicyCursor::new_at(policy_data, offset);
292 let (entry, _) = D::parse(cursor).map_err(Into::<anyhow::Error>::into)?;
293 Ok(entry)
294 })
295 }
296}
297
298fn compute_hash<V: Hash>(val: &V) -> u64 {
299 let mut hasher = RapidHasher::default();
300 val.hash(&mut hasher);
301 hasher.finish()
302}
303
304impl<D: Hashable + Parse> Parse for CustomKeyHashedView<D> {
305 type Error = anyhow::Error;
306
307 fn parse<'a>(cursor: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error> {
309 let (metadata, cursor) = le::U32::parse(cursor).map_err(Into::<anyhow::Error>::into)?;
311 let count = metadata.count();
312
313 let mut index = HashTable::with_capacity(count as usize);
315
316 let mut key_offset = cursor.offset();
317 let mut tail = cursor;
318 for _ in 0..count {
319 let (entry, next) = D::parse(tail).map_err(Into::<anyhow::Error>::into)?;
320 tail = next;
321
322 let key: &D::Key = entry.key();
323 index.insert_unique(compute_hash(&key), key_offset, |&key_offset| {
324 let policy_cursor = PolicyCursor::new_at(tail.data(), key_offset);
325 let (key, _) = D::Key::parse(policy_cursor)
326 .map_err(Into::<anyhow::Error>::into)
327 .expect("policy should be valid");
328 compute_hash::<D::Key>(&key)
329 });
330 key_offset = tail.offset();
331 }
332
333 Ok((Self { _phantom: PhantomData, index }, tail))
334 }
335}
336
337impl<D: Hashable + Parse> Validate for CustomKeyHashedView<D>
338where
339 SimpleArrayView<D::Value>: Validate<Error = anyhow::Error>,
340{
341 type Error = anyhow::Error;
342
343 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error> {
344 for key_offset in self.index.iter() {
345 let cursor = PolicyCursor::new_at(&context.data, *key_offset);
346 let (entry, _) = D::parse(cursor).map_err(Into::<anyhow::Error>::into)?;
347
348 entry.values().validate(context)?;
349 }
350 Ok(())
351 }
352}