structured_cms/
content.rs1use crate::{Error, ErrorCode, Octets, Result};
4use structured_asn1::{Element, Oid, Reader, Span, Tag, universal};
5
6#[derive(Debug)]
12pub struct ContentInfo<'a> {
13 kind: Oid<'a>,
14 content: Element<'a>,
15 span: Span,
16}
17
18impl<'a> ContentInfo<'a> {
19 pub fn read(reader: &mut Reader<'a>) -> Result<(Self, Reader<'a>)> {
26 let outer = reader
27 .expect(Tag::constructed(universal::SEQUENCE))
28 .map_err(|error| Error::encoding(error, "contentInfo"))?;
29 let result = Self::read_element(reader, &outer)?;
30 if !reader.is_empty() {
31 return Err(Error::schema(
32 ErrorCode::TrailingData,
33 "contentInfo",
34 reader.offset(),
35 ));
36 }
37 Ok(result)
38 }
39
40 pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<(Self, Reader<'a>)> {
45 const FIELD: &str = "contentInfo";
46 if element.tag() != Tag::constructed(universal::SEQUENCE) {
47 return Err(Error::schema(
48 ErrorCode::UnexpectedTag,
49 FIELD,
50 element.span().start,
51 ));
52 }
53 let mut inside = parent
54 .enter(element)
55 .map_err(|error| Error::encoding(error, FIELD))?;
56 let kind = inside
57 .read_oid()
58 .map_err(|error| Error::encoding(error, "contentInfo.contentType"))?;
59 let wrapper = inside
64 .expect(Tag::context(true, 0))
65 .map_err(|error| Error::encoding(error, "contentInfo.content"))?;
66 let mut explicit = inside
67 .enter(&wrapper)
68 .map_err(|error| Error::encoding(error, "contentInfo.content"))?;
69 let content = explicit
70 .next_element()
71 .map_err(|error| Error::encoding(error, "contentInfo.content"))?
72 .ok_or_else(|| {
73 Error::schema(
74 ErrorCode::MissingField,
75 "contentInfo.content",
76 wrapper.span().start,
77 )
78 })?;
79 if !explicit.is_empty() {
80 return Err(Error::schema(
81 ErrorCode::TrailingData,
82 "contentInfo.content",
83 explicit.offset(),
84 ));
85 }
86 if !inside.is_empty() {
87 return Err(Error::schema(
88 ErrorCode::TrailingData,
89 FIELD,
90 inside.offset(),
91 ));
92 }
93 Ok((
94 Self {
95 kind,
96 content,
97 span: element.span(),
98 },
99 explicit,
100 ))
101 }
102
103 #[must_use]
105 pub fn kind(&self) -> Oid<'a> {
106 self.kind
107 }
108
109 #[must_use]
111 pub fn content(&self) -> &Element<'a> {
112 &self.content
113 }
114
115 #[must_use]
117 pub fn span(&self) -> Span {
118 self.span
119 }
120}
121
122#[derive(Debug)]
124pub struct Encapsulated<'a> {
125 kind: Oid<'a>,
126 kind_encoding: &'a [u8],
127 content: Option<Octets<'a>>,
128 span: Span,
129}
130
131impl<'a> Encapsulated<'a> {
132 pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
137 const FIELD: &str = "signedData.encapContentInfo";
138 const KIND: &str = "signedData.encapContentInfo.eContentType";
139 if element.tag() != Tag::constructed(universal::SEQUENCE) {
140 return Err(Error::schema(
141 ErrorCode::UnexpectedTag,
142 FIELD,
143 element.span().start,
144 ));
145 }
146 let mut inside = parent
147 .enter(element)
148 .map_err(|error| Error::encoding(error, FIELD))?;
149 let kind_element = inside
150 .expect(Tag::primitive(universal::OID))
151 .map_err(|error| Error::encoding(error, KIND))?;
152 let kind = inside
153 .oid(&kind_element)
154 .map_err(|error| Error::encoding(error, KIND))?;
155 let content = if let Some(wrapper) = inside
156 .next_element()
157 .map_err(|error| Error::encoding(error, FIELD))?
158 {
159 const CONTENT: &str = "signedData.encapContentInfo.eContent";
160 if wrapper.tag() != Tag::context(true, 0) {
161 return Err(Error::schema(
162 ErrorCode::UnexpectedTag,
163 CONTENT,
164 wrapper.span().start,
165 ));
166 }
167 let mut explicit = inside
168 .enter(&wrapper)
169 .map_err(|error| Error::encoding(error, CONTENT))?;
170 let octets = explicit
171 .next_element()
172 .map_err(|error| Error::encoding(error, CONTENT))?
173 .ok_or_else(|| {
174 Error::schema(ErrorCode::MissingField, CONTENT, wrapper.span().start)
175 })?;
176 let content = Octets::read(&explicit, &octets, CONTENT)?;
177 if !explicit.is_empty() {
178 return Err(Error::schema(
179 ErrorCode::TrailingData,
180 CONTENT,
181 explicit.offset(),
182 ));
183 }
184 Some(content)
185 } else {
186 None
187 };
188 if !inside.is_empty() {
189 return Err(Error::schema(
190 ErrorCode::TrailingData,
191 FIELD,
192 inside.offset(),
193 ));
194 }
195 Ok(Self {
196 kind,
197 kind_encoding: kind_element.as_bytes(),
198 content,
199 span: element.span(),
200 })
201 }
202
203 #[must_use]
205 pub fn kind(&self) -> Oid<'a> {
206 self.kind
207 }
208
209 #[must_use]
211 pub fn kind_encoding(&self) -> &'a [u8] {
212 self.kind_encoding
213 }
214
215 #[must_use]
217 pub fn content(&self) -> Option<&Octets<'a>> {
218 self.content.as_ref()
219 }
220
221 #[must_use]
223 pub fn is_detached(&self) -> bool {
224 self.content.is_none()
225 }
226
227 #[must_use]
229 pub fn span(&self) -> Span {
230 self.span
231 }
232}