1use crate::{
4 error::Error,
5 zip::{Member, MemberId, ReadFailure},
6};
7use structured_asn1::{
8 Reader, Span,
9 memory::{OwnedVec, Work},
10 range::RangeSource,
11};
12use structured_cms::{ContentInfo, SignedData, evidence::EvidenceRecord, timestamp::Token};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum Syntax {
17 Empty,
19 Trailing,
21 ContentType,
23}
24
25#[derive(Debug)]
27pub enum CarriedError<E, D, G> {
28 Archive(Error<E>),
30 Encoding {
32 member: MemberId<D, G>,
34 physical: Span,
36 cause: structured_asn1::Error,
38 },
39 Cms {
41 member: MemberId<D, G>,
43 physical: Span,
45 cause: structured_cms::Error,
47 },
48 Syntax {
50 member: MemberId<D, G>,
52 physical: Span,
54 kind: Syntax,
56 },
57}
58
59pub struct Content<'v, 's, S: RangeSource> {
63 member: Member<'v, 's, S>,
64 bytes: OwnedVec<u8>,
65}
66
67impl<'v, 's, S: RangeSource> Member<'v, 's, S> {
68 pub async fn content<W: Work>(
71 &self,
72 work: &W,
73 ) -> Result<Content<'v, 's, S>, ReadFailure<S::Error, S::Document, S::Generation>> {
74 let bytes = self.read_bytes(work).await?;
75 let member =
76 self.archive()
77 .original(self.id(), work)
78 .map_err(|cause| ReadFailure::Processing {
79 member: self.id(),
80 cause,
81 })?;
82 Ok(Content { member, bytes })
83 }
84}
85
86pub type ResultOf<T, S> = Result<
88 T,
89 CarriedError<
90 <S as RangeSource>::Error,
91 <S as RangeSource>::Document,
92 <S as RangeSource>::Generation,
93 >,
94>;
95
96impl<'v, 's, S: RangeSource> Content<'v, 's, S> {
97 pub(crate) fn into_parts(self) -> (Member<'v, 's, S>, OwnedVec<u8>) {
98 (self.member, self.bytes)
99 }
100 #[must_use]
102 pub fn member(&self) -> &Member<'v, 's, S> {
103 &self.member
104 }
105 #[must_use]
107 pub fn bytes(&self) -> &[u8] {
108 &self.bytes
109 }
110 #[must_use]
116 pub fn enclosure(&self) -> Span {
117 self.member
118 .local_span()
119 .expect("complete original content has a local enclosure")
120 }
121 fn cursor<'q, W: Work + 'q>(&'q self, work: &W) -> ResultOf<Reader<'q>, S> {
122 self.member
123 .archive()
124 .admit(work, self.enclosure())
125 .map_err(CarriedError::Archive)?;
126 self.member
127 .session()
128 .carried(&self.bytes, work)
129 .map_err(|cause| self.encoding(cause))
130 }
131 fn encoding(
132 &self,
133 cause: structured_asn1::Error,
134 ) -> CarriedError<S::Error, S::Document, S::Generation> {
135 CarriedError::Encoding {
136 member: self.member.id(),
137 physical: self.enclosure(),
138 cause,
139 }
140 }
141 fn cms(
142 &self,
143 cause: structured_cms::Error,
144 ) -> CarriedError<S::Error, S::Document, S::Generation> {
145 CarriedError::Cms {
146 member: self.member.id(),
147 physical: self.enclosure(),
148 cause,
149 }
150 }
151 fn syntax(&self, kind: Syntax) -> CarriedError<S::Error, S::Document, S::Generation> {
152 CarriedError::Syntax {
153 member: self.member.id(),
154 physical: self.enclosure(),
155 kind,
156 }
157 }
158 pub fn read<'q, W: Work + 'q>(&'q self, work: &W) -> ResultOf<(SignedData<'q>, Reader<'q>), S> {
160 let mut root = self.cursor(work)?;
161 let (content, parent) = ContentInfo::read(&mut root).map_err(|cause| self.cms(cause))?;
162 parent
163 .execution()
164 .charge_work(content.kind().as_bytes().len() as u64)
165 .map_err(|cause| {
166 CarriedError::Archive(crate::error::resource(self.enclosure(), cause))
167 })?;
168 if content.kind() != structured_cms::oid::SIGNED_DATA {
169 return Err(self.syntax(Syntax::ContentType));
170 }
171 let message = SignedData::read_element(&parent, content.content())
172 .map_err(|cause| self.cms(cause))?;
173 self.require(&message, &parent, work)
174 .map_err(CarriedError::Archive)?;
175 Ok((message, parent))
176 }
177 pub fn read_timestamp<'q, W: Work + 'q>(
179 &'q self,
180 work: &W,
181 ) -> ResultOf<(Token<'q>, Reader<'q>), S> {
182 let mut reader = self.cursor(work)?;
183 let token = Token::read_from(&mut reader).map_err(|cause| self.cms(cause))?;
184 self.require(token.message(), &reader, work)
185 .map_err(CarriedError::Archive)?;
186 Ok((token, reader))
187 }
188 pub fn read_evidence<'q, W: Work + 'q>(
190 &'q self,
191 work: &W,
192 ) -> ResultOf<(EvidenceRecord<'q>, Reader<'q>), S> {
193 let mut reader = self.cursor(work)?;
194 let element = reader
195 .next_element()
196 .map_err(|cause| self.encoding(cause))?
197 .ok_or_else(|| self.syntax(Syntax::Empty))?;
198 if !reader.is_empty() {
199 return Err(self.syntax(Syntax::Trailing));
200 }
201 let record = EvidenceRecord::read(&reader, &element).map_err(|cause| self.cms(cause))?;
202 Ok((record, reader))
203 }
204 pub(crate) fn require<W: Work>(
205 &self,
206 message: &SignedData<'_>,
207 parent: &Reader<'_>,
208 work: &W,
209 ) -> Result<(), Error<S::Error>> {
210 self.require_original(message.as_bytes(), message.span().start, parent, work)
211 }
212 pub(crate) fn require_original<W: Work>(
213 &self,
214 original: &[u8],
215 offset: u64,
216 parent: &Reader<'_>,
217 work: &W,
218 ) -> Result<(), Error<S::Error>> {
219 self.member.archive().admit(work, self.enclosure())?;
220 let at = usize::try_from(offset).map_err(|_| Error::Foreign {
221 range: self.enclosure(),
222 })?;
223 let end = at.checked_add(original.len()).ok_or(Error::Foreign {
224 range: self.enclosure(),
225 })?;
226 if !self.member.session().owns(parent)
227 || self
228 .bytes
229 .get(at..end)
230 .is_none_or(|bytes| !core::ptr::eq(bytes, original))
231 {
232 return Err(Error::Foreign {
233 range: self.enclosure(),
234 });
235 }
236 Ok(())
237 }
238}