1use super::Basic;
4use crate::{
5 Xades, certificate::CheckedPathCertificate, material, prepare::Preparation,
6 unsigned::Requirements,
7};
8use structured_ltv::baseline::{ArchiveMaterial, Archives, LongTerm, Timed};
9
10type BasicOf<'a, N, D, G> = Basic<'a, 'a, 'a, 'a, N, D, G>;
11type TimedOf<'a, N, D, G> = Timed<
12 'a,
13 'a,
14 'a,
15 BasicOf<'a, N, D, G>,
16 CheckedPathCertificate<'a, 'a, N, D, G>,
17 N,
18 D,
19 G,
20 Xades,
21>;
22type CredentialsOf<'a, A, N, D, G> = material::credentials::Report<'a, 'a, 'a, A, N, D, G>;
23type LongTermOf<'a, A, N, D, G> = LongTerm<
24 'a,
25 TimedOf<'a, N, D, G>,
26 material::Checks<'a, 'a, 'a, 'a, 'a, N, D, G>,
27 CredentialsOf<'a, A, N, D, G>,
28>;
29type ArchivesOf<'a, A, N, D, G> = Archives<
30 'a,
31 Preparation<N, D, G>,
32 ArchiveMaterial<
33 'a,
34 structured_ltv::material::ParticipantMaterial<
35 'a,
36 'a,
37 'a,
38 'a,
39 'a,
40 N,
41 D,
42 G,
43 material::Placement<N>,
44 Xades,
45 >,
46 CredentialsOf<'a, A, N, D, G>,
47 >,
48>;
49
50pub enum Evidence<'a, A, N, D, G> {
53 Basic(&'a BasicOf<'a, N, D, G>),
55 Timestamped(&'a TimedOf<'a, N, D, G>),
57 LongTerm(&'a LongTermOf<'a, A, N, D, G>),
59 Archival {
61 long_term: &'a LongTermOf<'a, A, N, D, G>,
63 archives: &'a ArchivesOf<'a, A, N, D, G>,
65 },
66}
67
68impl<'a, N, D, G> Evidence<'a, (), N, D, G> {
71 #[must_use]
73 pub fn basic(report: &'a BasicOf<'a, N, D, G>) -> Self {
74 Self::Basic(report)
75 }
76 #[must_use]
78 pub fn timestamped(report: &'a TimedOf<'a, N, D, G>) -> Self {
79 Self::Timestamped(report)
80 }
81}
82
83impl<A, N: Copy, D: Copy, G: Copy> Evidence<'_, A, N, D, G> {
84 #[must_use]
86 pub fn level(&self) -> Requirements {
87 match self {
88 Self::Basic(_) => Requirements::Basic,
89 Self::Timestamped(_) => Requirements::Timestamped,
90 Self::LongTerm(_) => Requirements::LongTerm,
91 Self::Archival { .. } => Requirements::Archival,
92 }
93 }
94
95 pub(crate) fn prepared(&self) -> &Preparation<N, D, G> {
96 match self {
97 Self::Basic(basic) => basic.inputs().fields.prepared(),
98 Self::Timestamped(timed) => timed.basic().inputs().fields.prepared(),
99 Self::LongTerm(long_term) | Self::Archival { long_term, .. } => {
100 long_term.timed().basic().inputs().fields.prepared()
101 }
102 }
103 }
104}
105
106pub struct Assessment<'a, A, N, D, G> {
110 evidence: Evidence<'a, A, N, D, G>,
111 met: bool,
112}
113
114impl<'a, A, N: Copy, D: Copy, G: Copy> Assessment<'a, A, N, D, G> {
115 #[must_use]
117 pub fn requested(&self) -> Requirements {
118 self.evidence.level()
119 }
120 #[must_use]
122 pub fn evidence(&self) -> &Evidence<'a, A, N, D, G> {
123 &self.evidence
124 }
125 #[must_use]
127 pub fn all_requirements_met(&self) -> bool {
128 self.met
129 }
130}
131
132#[derive(Debug, Clone, Copy, PartialEq, Eq)]
134pub enum LevelError {
135 Mismatch {
137 requested: Requirements,
139 supplied: Requirements,
141 },
142 Foreign,
145}
146
147pub fn assess<A, N: Copy, D: Copy, G: Copy>(
162 evidence: Evidence<'_, A, N, D, G>,
163) -> Result<Assessment<'_, A, N, D, G>, LevelError> {
164 let requested = evidence.prepared().requirements();
165 let supplied = evidence.level();
166 if requested != supplied {
167 return Err(LevelError::Mismatch {
168 requested,
169 supplied,
170 });
171 }
172 let met = match &evidence {
173 Evidence::Basic(basic) => basic.all_root_requirements_met(),
174 Evidence::Timestamped(timed) => timed_met(timed),
175 Evidence::LongTerm(long_term) => long_term_met(long_term),
176 Evidence::Archival {
177 long_term,
178 archives,
179 } => {
180 let census = long_term.credentials().credentials();
181 if !core::ptr::eq(archives.census(), evidence.prepared())
182 || archives
183 .reports()
184 .iter()
185 .any(|report| !core::ptr::eq(report.credentials().credentials(), census))
186 {
187 return Err(LevelError::Foreign);
188 }
189 long_term_met(long_term) && archives.all_archive_material_covered()
190 }
191 };
192 Ok(Assessment { evidence, met })
193}
194
195fn timed_met<N: Copy, D: Copy, G: Copy>(timed: &TimedOf<'_, N, D, G>) -> bool {
196 timed.basic().all_root_requirements_met() && timed.all_static_time_requirements_met()
197}
198
199fn long_term_met<A, N: Copy, D: Copy, G: Copy>(long_term: &LongTermOf<'_, A, N, D, G>) -> bool {
200 timed_met(long_term.timed()) && long_term.all_material_requirements_met()
201}