structured_ltv/pki/
root_visits.rs1use super::closure::{Key, follow};
3use super::{AuthorityClosure, AuthorityClosureError, AuthorityNode, AuthorityOrigin};
4use structured_asn1::memory::{MemoryError, OwnedMap, OwnedVec, Work};
5
6#[derive(Debug)]
9pub enum AuthorityVisitError<E> {
10 Processing(AuthorityClosureError),
12 Visitor(E),
14}
15
16struct VisitState {
17 index: usize,
18 root: Option<usize>,
19}
20struct Pending<'view, 'document, W: Work> {
21 index: OwnedMap<Key<'view, 'document>, VisitState, W>,
22 queue: OwnedVec<usize, W>,
23}
24impl<'view, 'document, W: Work> Pending<'view, 'document, W> {
25 fn need(
26 &mut self,
27 key: Key<'view, 'document>,
28 root: usize,
29 origin: AuthorityOrigin,
30 work: &W,
31 ) -> Result<(), AuthorityClosureError> {
32 let state = self
33 .index
34 .get_mut(&key, work)?
35 .ok_or(AuthorityClosureError::MissingPath { origin })?;
36 work.charge_work(1)?;
37 if state.root != Some(root) {
38 self.queue.try_push(state.index)?;
39 state.root = Some(root);
40 }
41 Ok(())
42 }
43}
44
45impl<'view, 'certificate, 'document> AuthorityClosure<'view, 'certificate, 'document> {
46 pub fn visit_roots<E, W: Work>(
60 &self,
61 work: &W,
62 mut visitor: impl FnMut(
63 usize,
64 &'view AuthorityNode<'view, 'certificate, 'document>,
65 ) -> Result<(), E>,
66 ) -> Result<(), AuthorityVisitError<E>> {
67 let processing = AuthorityVisitError::Processing;
68 let resource = |cause: MemoryError| processing(AuthorityClosureError::Resource(cause));
69 work.charge_work(1).map_err(resource)?;
70 let mut pending = Pending {
71 index: work.map(),
72 queue: work.vector(),
73 };
74 let mut responders = work.map();
75 for (index, node) in self.nodes().iter().enumerate() {
76 work.charge_work(1).map_err(resource)?;
77 let key = Key {
78 path: node.statuses.path(),
79 at: node.statuses.evaluated_at(),
80 };
81 if pending
82 .index
83 .try_insert(key, VisitState { index, root: None })
84 .map_err(resource)?
85 .is_some()
86 {
87 return Err(processing(AuthorityClosureError::DuplicateNode { index }));
88 }
89 for responder in node.responders {
90 work.charge_work(1).map_err(resource)?;
91 let key = core::ptr::from_ref(responder.target()).addr();
92 if responders
93 .try_insert(key, *responder)
94 .map_err(resource)?
95 .is_some()
96 {
97 return Err(processing(AuthorityClosureError::DuplicateResponder {
98 node: index,
99 }));
100 }
101 }
102 }
103 for (root, statuses) in self.roots().iter().enumerate() {
104 work.charge_work(1).map_err(resource)?;
105 pending.queue.clear();
106 pending
107 .need(
108 Key {
109 path: statuses.path(),
110 at: statuses.evaluated_at(),
111 },
112 root,
113 AuthorityOrigin::Root { index: root },
114 work,
115 )
116 .map_err(processing)?;
117 let mut cursor = 0;
118 while cursor < pending.queue.len() {
119 work.charge_work(1).map_err(resource)?;
120 let index = pending.queue[cursor];
121 let node = self.nodes()[index];
122 visitor(root, node).map_err(AuthorityVisitError::Visitor)?;
123 follow(
124 node.statuses,
125 index,
126 &responders,
127 &mut |path, at, origin, work| {
128 pending.need(Key { path, at }, root, origin, work)
129 },
130 work,
131 )
132 .map_err(processing)?;
133 cursor += 1;
134 }
135 }
136 Ok(())
137 }
138}