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 content: Option<Octets<'a>>,
127 span: Span,
128}
129
130impl<'a> Encapsulated<'a> {
131 pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
136 const FIELD: &str = "signedData.encapContentInfo";
137 if element.tag() != Tag::constructed(universal::SEQUENCE) {
138 return Err(Error::schema(
139 ErrorCode::UnexpectedTag,
140 FIELD,
141 element.span().start,
142 ));
143 }
144 let mut inside = parent
145 .enter(element)
146 .map_err(|error| Error::encoding(error, FIELD))?;
147 let kind = inside
148 .read_oid()
149 .map_err(|error| Error::encoding(error, "signedData.encapContentInfo.eContentType"))?;
150 let content = if let Some(wrapper) = inside
151 .next_element()
152 .map_err(|error| Error::encoding(error, FIELD))?
153 {
154 const CONTENT: &str = "signedData.encapContentInfo.eContent";
155 if wrapper.tag() != Tag::context(true, 0) {
156 return Err(Error::schema(
157 ErrorCode::UnexpectedTag,
158 CONTENT,
159 wrapper.span().start,
160 ));
161 }
162 let mut explicit = inside
163 .enter(&wrapper)
164 .map_err(|error| Error::encoding(error, CONTENT))?;
165 let octets = explicit
166 .next_element()
167 .map_err(|error| Error::encoding(error, CONTENT))?
168 .ok_or_else(|| {
169 Error::schema(ErrorCode::MissingField, CONTENT, wrapper.span().start)
170 })?;
171 let content = Octets::read(&explicit, &octets, CONTENT)?;
172 if !explicit.is_empty() {
173 return Err(Error::schema(
174 ErrorCode::TrailingData,
175 CONTENT,
176 explicit.offset(),
177 ));
178 }
179 Some(content)
180 } else {
181 None
182 };
183 if !inside.is_empty() {
184 return Err(Error::schema(
185 ErrorCode::TrailingData,
186 FIELD,
187 inside.offset(),
188 ));
189 }
190 Ok(Self {
191 kind,
192 content,
193 span: element.span(),
194 })
195 }
196
197 #[must_use]
199 pub fn kind(&self) -> Oid<'a> {
200 self.kind
201 }
202
203 #[must_use]
205 pub fn content(&self) -> Option<&Octets<'a>> {
206 self.content.as_ref()
207 }
208
209 #[must_use]
211 pub fn is_detached(&self) -> bool {
212 self.content.is_none()
213 }
214
215 #[must_use]
217 pub fn span(&self) -> Span {
218 self.span
219 }
220}