11//! Catalyst Signed Document Metadata.
22use std:: fmt:: { Display , Formatter } ;
33
4+ mod additional_fields;
45mod content_encoding;
56mod content_type;
67mod document_id;
78mod document_ref;
89mod document_type;
910mod document_version;
1011
12+ use additional_fields:: AdditionalFields ;
13+ use anyhow:: anyhow;
1114pub use catalyst_types:: uuid:: { V4 as UuidV4 , V7 as UuidV7 } ;
1215pub use content_encoding:: ContentEncoding ;
1316pub use content_type:: ContentType ;
@@ -45,24 +48,6 @@ pub struct Metadata {
4548 content_errors : Vec < String > ,
4649}
4750
48- /// Additional Metadata Fields.
49- ///
50- /// These values are extracted from the COSE Sign protected header labels.
51- #[ derive( Default , Debug , serde:: Deserialize ) ]
52- struct AdditionalFields {
53- /// Reference to the latest document.
54- #[ serde( rename = "ref" ) ]
55- doc_ref : Option < DocumentRef > ,
56- /// Hash of the referenced document bytes.
57- ref_hash : Option < Vec < u8 > > ,
58- /// Reference to the document template.
59- template : Option < DocumentRef > ,
60- /// Reference to the document reply.
61- reply : Option < DocumentRef > ,
62- /// Reference to the document section.
63- section : Option < String > ,
64- }
65-
6651impl Metadata {
6752 /// Are there any validation errors (as opposed to structural errors).
6853 #[ must_use]
@@ -100,12 +85,6 @@ impl Metadata {
10085 self . content_encoding
10186 }
10287
103- /// Return Last Document Reference `Option<Vec<u8>>`.
104- #[ must_use]
105- pub fn doc_ref_hash ( & self ) -> Option < Vec < u8 > > {
106- self . extra . ref_hash . clone ( )
107- }
108-
10988 /// Return Last Document Reference `Option<DocumentRef>`.
11089 #[ must_use]
11190 pub fn doc_ref ( & self ) -> Option < DocumentRef > {
@@ -165,7 +144,6 @@ impl Default for Metadata {
165144}
166145
167146impl From < & coset:: ProtectedHeader > for Metadata {
168- #[ allow( clippy:: too_many_lines) ]
169147 fn from ( protected : & coset:: ProtectedHeader ) -> Self {
170148 let mut metadata = Metadata :: default ( ) ;
171149 let mut errors = Vec :: new ( ) ;
@@ -175,14 +153,14 @@ impl From<&coset::ProtectedHeader> for Metadata {
175153 match ContentType :: try_from ( iana_content_type) {
176154 Ok ( content_type) => metadata. content_type = content_type,
177155 Err ( e) => {
178- errors. push ( format ! ( "Invalid Document Content-Type: {e}" ) ) ;
156+ errors. push ( anyhow ! ( "Invalid Document Content-Type: {e}" ) ) ;
179157 } ,
180158 }
181159 } ,
182160 None => {
183- errors. push (
184- "COSE document protected header `content-type` field is missing" . to_string ( ) ,
185- ) ;
161+ errors. push ( anyhow ! (
162+ "COSE document protected header `content-type` field is missing"
163+ ) ) ;
186164 } ,
187165 }
188166
@@ -195,11 +173,11 @@ impl From<&coset::ProtectedHeader> for Metadata {
195173 metadata. content_encoding = Some ( encoding) ;
196174 } ,
197175 Err ( e) => {
198- errors. push ( format ! ( "Invalid Document Content Encoding: {e}" ) ) ;
176+ errors. push ( anyhow ! ( "Invalid Document Content Encoding: {e}" ) ) ;
199177 } ,
200178 }
201179 } else {
202- errors. push ( format ! (
180+ errors. push ( anyhow ! (
203181 "Invalid COSE document protected header '{CONTENT_ENCODING_KEY}' is missing"
204182 ) ) ;
205183 }
@@ -212,11 +190,13 @@ impl From<&coset::ProtectedHeader> for Metadata {
212190 metadata. doc_type = doc_type_uuid. into ( ) ;
213191 } ,
214192 Err ( e) => {
215- errors. push ( format ! ( "Document `type` is invalid: {e}" ) ) ;
193+ errors. push ( anyhow ! ( "Document `type` is invalid: {e}" ) ) ;
216194 } ,
217195 }
218196 } else {
219- errors. push ( "Invalid COSE protected header, missing `type` field" . to_string ( ) ) ;
197+ errors. push ( anyhow ! (
198+ "Invalid COSE protected header, missing `type` field"
199+ ) ) ;
220200 }
221201
222202 match cose_protected_header_find ( protected, |key| {
@@ -228,11 +208,11 @@ impl From<&coset::ProtectedHeader> for Metadata {
228208 metadata. id = doc_id_uuid. into ( ) ;
229209 } ,
230210 Err ( e) => {
231- errors. push ( format ! ( "Document `id` is invalid: {e}" ) ) ;
211+ errors. push ( anyhow ! ( "Document `id` is invalid: {e}" ) ) ;
232212 } ,
233213 }
234214 } ,
235- None => errors. push ( "Invalid COSE protected header, missing `id` field" . to_string ( ) ) ,
215+ None => errors. push ( anyhow ! ( "Invalid COSE protected header, missing `id` field" ) ) ,
236216 } ;
237217
238218 match cose_protected_header_find ( protected, |key| {
@@ -242,83 +222,32 @@ impl From<&coset::ProtectedHeader> for Metadata {
242222 match UuidV7 :: try_from ( doc_ver) {
243223 Ok ( doc_ver_uuid) => {
244224 if doc_ver_uuid. uuid ( ) < metadata. id . uuid ( ) {
245- errors. push ( format ! (
225+ errors. push ( anyhow ! (
246226 "Document Version {doc_ver_uuid} cannot be smaller than Document ID {}" , metadata. id
247227 ) ) ;
248228 } else {
249229 metadata. ver = doc_ver_uuid. into ( ) ;
250230 }
251231 } ,
252232 Err ( e) => {
253- errors. push ( format ! (
233+ errors. push ( anyhow ! (
254234 "Invalid COSE protected header `ver` field, err: {e}"
255235 ) ) ;
256236 } ,
257237 }
258238 } ,
259- None => errors. push ( "Invalid COSE protected header, missing `ver` field" . to_string ( ) ) ,
260- }
261-
262- if let Some ( cbor_doc_ref) = cose_protected_header_find ( protected, |key| {
263- key == & coset:: Label :: Text ( "ref" . to_string ( ) )
264- } ) {
265- match DocumentRef :: try_from ( cbor_doc_ref) {
266- Ok ( doc_ref) => {
267- metadata. extra . doc_ref = Some ( doc_ref) ;
268- } ,
269- Err ( e) => {
270- errors. push ( format ! (
271- "Invalid COSE protected header `ref` field, err: {e}"
272- ) ) ;
273- } ,
274- }
275- }
276-
277- if let Some ( cbor_doc_template) = cose_protected_header_find ( protected, |key| {
278- key == & coset:: Label :: Text ( "template" . to_string ( ) )
279- } ) {
280- match DocumentRef :: try_from ( cbor_doc_template) {
281- Ok ( doc_template) => {
282- metadata. extra . template = Some ( doc_template) ;
283- } ,
284- Err ( e) => {
285- errors. push ( format ! (
286- "Invalid COSE protected header `template` field, err: {e}"
287- ) ) ;
288- } ,
289- }
239+ None => {
240+ errors. push ( anyhow ! (
241+ "Invalid COSE protected header, missing `ver` field"
242+ ) ) ;
243+ } ,
290244 }
291245
292- if let Some ( cbor_doc_reply) = cose_protected_header_find ( protected, |key| {
293- key == & coset:: Label :: Text ( "reply" . to_string ( ) )
294- } ) {
295- match DocumentRef :: try_from ( cbor_doc_reply) {
296- Ok ( doc_reply) => {
297- metadata. extra . reply = Some ( doc_reply) ;
298- } ,
299- Err ( e) => {
300- errors. push ( format ! (
301- "Invalid COSE protected header `reply` field, err: {e}"
302- ) ) ;
303- } ,
304- }
305- }
246+ match AdditionalFields :: try_from ( protected) {
247+ Ok ( extra) => metadata. extra = extra,
248+ Err ( e) => errors. extend ( e) ,
249+ } ;
306250
307- if let Some ( cbor_doc_section) = cose_protected_header_find ( protected, |key| {
308- key == & coset:: Label :: Text ( "section" . to_string ( ) )
309- } ) {
310- match cbor_doc_section. clone ( ) . into_text ( ) {
311- Ok ( doc_section) => {
312- metadata. extra . section = Some ( doc_section) ;
313- } ,
314- Err ( e) => {
315- errors. push ( format ! (
316- "Invalid COSE protected header `section` field, err: {e:?}"
317- ) ) ;
318- } ,
319- }
320- }
321- metadata. content_errors = errors;
322251 metadata
323252 }
324253}
0 commit comments