22
33mod builder;
44mod content;
5- mod error;
5+ pub mod error;
66mod metadata;
77mod signature;
8+ mod utils;
89
910use std:: {
1011 convert:: TryFrom ,
1112 fmt:: { Display , Formatter } ,
1213 sync:: Arc ,
1314} ;
1415
15- use anyhow:: anyhow;
1616pub use builder:: Builder ;
17+ use catalyst_types:: problem_report:: ProblemReport ;
1718pub use content:: Content ;
1819use coset:: { CborSerializable , Header } ;
20+ use error:: CatalystSignedDocError ;
1921pub use metadata:: { DocumentRef , ExtraFields , Metadata , UuidV4 , UuidV7 } ;
2022pub use minicbor:: { decode, encode, Decode , Decoder , Encode } ;
2123pub use signature:: { KidUri , Signatures } ;
24+ use utils:: context:: DecodeSignDocCtx ;
2225
2326/// Inner type that holds the Catalyst Signed Document with parsing errors.
2427#[ derive( Debug , Clone ) ]
@@ -104,8 +107,20 @@ impl CatalystSignedDocument {
104107 }
105108}
106109
107- impl Decode < ' _ , ( ) > for CatalystSignedDocument {
108- fn decode ( d : & mut Decoder < ' _ > , ( ) : & mut ( ) ) -> Result < Self , decode:: Error > {
110+ impl TryFrom < & [ u8 ] > for CatalystSignedDocument {
111+ type Error = CatalystSignedDocError ;
112+
113+ fn try_from ( value : & [ u8 ] ) -> Result < Self , Self :: Error > {
114+ let error_report = ProblemReport :: new ( "Catalyst Signed Document" ) ;
115+ let mut ctx = DecodeSignDocCtx { error_report } ;
116+ let decoded: CatalystSignedDocument = minicbor:: decode_with ( value, & mut ctx)
117+ . map_err ( |e| CatalystSignedDocError :: new ( ctx. error_report , e. into ( ) ) ) ?;
118+ Ok ( decoded)
119+ }
120+ }
121+
122+ impl Decode < ' _ , DecodeSignDocCtx > for CatalystSignedDocument {
123+ fn decode ( d : & mut Decoder < ' _ > , ctx : & mut DecodeSignDocCtx ) -> Result < Self , decode:: Error > {
109124 let start = d. position ( ) ;
110125 d. skip ( ) ?;
111126 let end = d. position ( ) ;
@@ -115,40 +130,67 @@ impl Decode<'_, ()> for CatalystSignedDocument {
115130 . ok_or ( minicbor:: decode:: Error :: end_of_input ( ) ) ?;
116131
117132 let cose_sign = coset:: CoseSign :: from_slice ( cose_bytes) . map_err ( |e| {
133+ ctx. error_report . invalid_value (
134+ "COSE sign document bytes" ,
135+ & format ! ( "{:?}" , & cose_bytes) ,
136+ & format ! ( "Cannot convert bytes to CoseSign {e:?}" ) ,
137+ "Creating COSE Sign document" ,
138+ ) ;
118139 minicbor:: decode:: Error :: message ( format ! ( "Invalid COSE Sign document: {e}" ) )
119140 } ) ?;
120141
121- let mut errors = Vec :: new ( ) ;
122-
123- let metadata = Metadata :: try_from ( & cose_sign. protected ) . map_or_else (
124- |e| {
125- errors. extend ( e. 0 . 0 ) ;
126- None
127- } ,
128- Some ,
129- ) ;
130- let signatures = Signatures :: try_from ( & cose_sign. signatures ) . map_or_else (
131- |e| {
132- errors. extend ( e. 0 . 0 ) ;
133- None
134- } ,
135- Some ,
136- ) ;
142+ let metadata = Metadata :: from_protected_header ( & cose_sign. protected , & ctx. error_report )
143+ . map_or_else (
144+ |e| {
145+ ctx. error_report . conversion_error (
146+ "COSE sign protected header" ,
147+ & format ! ( "{:?}" , & cose_sign. protected) ,
148+ & format ! ( "Expected Metadata: {e:?}" ) ,
149+ "Converting COSE Sign protected header to Metadata" ,
150+ ) ;
151+ None
152+ } ,
153+ Some ,
154+ ) ;
155+ let signatures = Signatures :: from_cose_sig ( & cose_sign. signatures , & ctx. error_report )
156+ . map_or_else (
157+ |e| {
158+ ctx. error_report . conversion_error (
159+ "COSE sign signatures" ,
160+ & format ! ( "{:?}" , & cose_sign. signatures) ,
161+ & format ! ( "Expected Signatures {e:?}" ) ,
162+ "Converting COSE Sign signatures to Signatures" ,
163+ ) ;
164+ None
165+ } ,
166+ Some ,
167+ ) ;
137168
138169 if cose_sign. payload . is_none ( ) {
139- errors. push ( anyhow ! ( "Document Content is missing" ) ) ;
170+ ctx. error_report
171+ . missing_field ( "COSE Sign Payload" , "Missing document content (payload)" ) ;
140172 }
141173
142174 match ( cose_sign. payload , metadata, signatures) {
143175 ( Some ( payload) , Some ( metadata) , Some ( signatures) ) => {
144176 let content = Content :: from_encoded (
145- payload,
177+ payload. clone ( ) ,
146178 metadata. content_type ( ) ,
147179 metadata. content_encoding ( ) ,
148180 )
149181 . map_err ( |e| {
150- errors. push ( anyhow ! ( "Invalid Document Content: {e}" ) ) ;
151- minicbor:: decode:: Error :: message ( error:: Error :: from ( errors) )
182+ ctx. error_report . invalid_value (
183+ "Document Content" ,
184+ & format ! (
185+ "Given value {:?}, {:?}, {:?}" ,
186+ payload,
187+ metadata. content_type( ) ,
188+ metadata. content_encoding( )
189+ ) ,
190+ & format ! ( "{e:?}" ) ,
191+ "Creating document content" ,
192+ ) ;
193+ minicbor:: decode:: Error :: message ( "Failed to create Document Content" )
152194 } ) ?;
153195
154196 Ok ( InnerCatalystSignedDocument {
@@ -158,7 +200,11 @@ impl Decode<'_, ()> for CatalystSignedDocument {
158200 }
159201 . into ( ) )
160202 } ,
161- _ => Err ( minicbor:: decode:: Error :: message ( error:: Error :: from ( errors) ) ) ,
203+ _ => {
204+ Err ( minicbor:: decode:: Error :: message (
205+ "Failed to decode Catalyst Signed Document" ,
206+ ) )
207+ } ,
162208 }
163209 }
164210}
@@ -238,8 +284,8 @@ mod tests {
238284
239285 let mut bytes = Vec :: new ( ) ;
240286 minicbor:: encode_with ( doc, & mut bytes, & mut ( ) ) . unwrap ( ) ;
241- let decoded : CatalystSignedDocument =
242- minicbor :: decode_with ( bytes. as_slice ( ) , & mut ( ) ) . unwrap ( ) ;
287+
288+ let decoded : CatalystSignedDocument = bytes. as_slice ( ) . try_into ( ) . unwrap ( ) ;
243289
244290 assert_eq ! ( decoded. doc_type( ) , uuid_v4) ;
245291 assert_eq ! ( decoded. doc_id( ) , uuid_v7) ;
0 commit comments