1use super::{ArtifactRef, ArtifactUses, Index, IndexError, Occurrence};
4use crate::source::{Query, Snapshot};
5use crate::timestamp::TimestampScope;
6use structured_asn1::memory::{OwnedVec, Work};
7
8pub struct IncorporatedArtifact<'certificate, 'document, N, D, G, P> {
11 artifact: ArtifactRef<'certificate, 'document>,
12 occurrence: Option<Occurrence<N, D, G, P>>,
13}
14
15impl<'certificate, 'document, N: Copy, D: Copy, G: Copy, P: Copy>
16 IncorporatedArtifact<'certificate, 'document, N, D, G, P>
17{
18 #[must_use]
20 pub fn artifact(&self) -> ArtifactRef<'certificate, 'document> {
21 self.artifact
22 }
23 #[must_use]
25 pub fn occurrence(&self) -> Option<Occurrence<N, D, G, P>> {
26 self.occurrence
27 }
28}
29
30pub struct Incorporation<'certificate, 'document, N, D, G, P> {
35 snapshot: Snapshot<D, G>,
36 signature: N,
37 entries: OwnedVec<IncorporatedArtifact<'certificate, 'document, N, D, G, P>>,
38 all_present: bool,
39}
40
41impl<'certificate, 'document, N: Copy, D: Copy, G: Copy, P: Copy>
42 Incorporation<'certificate, 'document, N, D, G, P>
43{
44 #[must_use]
46 pub fn snapshot(&self) -> Snapshot<D, G> {
47 self.snapshot
48 }
49 #[must_use]
51 pub fn signature(&self) -> N {
52 self.signature
53 }
54 #[must_use]
56 pub fn entries(&self) -> &[IncorporatedArtifact<'certificate, 'document, N, D, G, P>] {
57 &self.entries
58 }
59 #[must_use]
61 pub fn all_present(&self) -> bool {
62 self.all_present
63 }
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum IncorporationError<N> {
69 Scope,
71 Index(IndexError<N>),
73}
74
75pub fn incorporation<'certificate, 'document, N, D, G, P, O, W, Q, I>(
84 uses: &ArtifactUses<'_, '_, '_, 'certificate, 'document, N, D, G, I>,
85 index: &Index<'_, N, D, G, P, O, W, I>,
86 query: &Q,
87) -> Result<Incorporation<'certificate, 'document, N, D, G, P>, IncorporationError<N>>
88where
89 N: Copy + Eq,
90 D: Copy + Eq,
91 G: Copy + Eq,
92 P: Copy,
93 W: Work,
94 Q: Query<Id = N, Document = D, Generation = G>,
95{
96 let required = uses.inputs().requirements();
97 let TimestampScope::All(location) = required.scope() else {
98 return Err(IncorporationError::Scope);
99 };
100 if location.snapshot != query.snapshot() {
101 return Err(IncorporationError::Index(IndexError::Foreign {
102 signature: required.signature(),
103 }));
104 }
105 index
106 .require_signature(required.signature(), query)
107 .map_err(IncorporationError::Index)?;
108 let resource = |cause| {
109 IncorporationError::Index(IndexError::Resource {
110 signature: required.signature(),
111 cause,
112 })
113 };
114 let mut entries = query.execution().vector();
115 entries
116 .try_reserve_exact(uses.entries().len())
117 .map_err(resource)?;
118 let mut all_present = true;
119 for ordinal in 0..uses.entries().len() {
120 query
121 .admit(required.signature(), 2)
122 .map_err(|cause| IncorporationError::Index(IndexError::Scope(cause)))?;
123 let artifact = uses.entries()[ordinal].artifact();
124 let mut copies = index
125 .artifact(artifact, query)
126 .map_err(IncorporationError::Index)?;
127 let occurrence = copies
128 .next()
129 .transpose()
130 .map_err(IncorporationError::Index)?;
131 if occurrence.is_none() {
132 all_present = false;
133 }
134 entries
135 .try_push(IncorporatedArtifact {
136 artifact,
137 occurrence,
138 })
139 .map_err(resource)?;
140 }
141 index
142 .require_signature(required.signature(), query)
143 .map_err(IncorporationError::Index)?;
144 Ok(Incorporation {
145 snapshot: location.snapshot,
146 signature: required.signature(),
147 entries: entries.into_owned(),
148 all_present,
149 })
150}