@@ -35,10 +35,10 @@ pub struct Metadata {
3535 /// Document Version `UUIDv7`.
3636 ver : DocumentVersion ,
3737 /// Document Payload Content Type.
38- #[ serde( default , rename = "content-type" ) ]
38+ #[ serde( rename = "content-type" ) ]
3939 content_type : ContentType ,
4040 /// Document Payload Content Encoding.
41- #[ serde( default , rename = "content-encoding" ) ]
41+ #[ serde( rename = "content-encoding" ) ]
4242 content_encoding : Option < ContentEncoding > ,
4343 /// Additional Metadata Fields.
4444 #[ serde( flatten) ]
@@ -90,131 +90,136 @@ impl Display for Metadata {
9090 }
9191}
9292
93- impl Default for Metadata {
94- fn default ( ) -> Self {
95- Self {
96- doc_type : DocumentType :: invalid ( ) ,
97- id : DocumentId :: invalid ( ) ,
98- ver : DocumentVersion :: invalid ( ) ,
99- content_type : ContentType :: default ( ) ,
100- content_encoding : None ,
101- extra : AdditionalFields :: default ( ) ,
102- }
103- }
104- }
105-
10693impl TryFrom < & coset:: ProtectedHeader > for Metadata {
10794 type Error = crate :: error:: Error ;
10895
10996 #[ allow( clippy:: too_many_lines) ]
11097 fn try_from ( protected : & coset:: ProtectedHeader ) -> Result < Self , Self :: Error > {
111- let mut metadata = Metadata :: default ( ) ;
11298 let mut errors = Vec :: new ( ) ;
11399
114- match protected. header . content_type . as_ref ( ) {
115- Some ( iana_content_type ) => {
116- match ContentType :: try_from ( iana_content_type ) {
117- Ok ( content_type ) => metadata . content_type = content_type ,
118- Err ( e ) => {
119- errors . push ( anyhow ! ( "Invalid Document Content-Type: {e}" ) ) ;
120- } ,
121- }
122- } ,
123- None => {
124- errors . push ( anyhow ! (
125- "COSE document protected header `content-type` field is missing"
126- ) ) ;
127- } ,
100+ let content_type = protected. header . content_type . as_ref ( ) . and_then ( |value| {
101+ ContentType :: try_from ( value ) . map_or_else (
102+ |e| {
103+ errors . push ( anyhow ! ( "Invalid Document Content-Type: {e}" ) ) ;
104+ None
105+ } ,
106+ Some ,
107+ )
108+ } ) ;
109+
110+ if content_type . is_none ( ) {
111+ errors . push ( anyhow ! (
112+ "Invalid COSE protected header, missing Content-Type field"
113+ ) ) ;
128114 }
129115
130- if let Some ( value ) = cose_protected_header_find (
131- protected ,
132- |key| matches ! ( key , coset :: Label :: Text ( label ) if label . eq_ignore_ascii_case ( CONTENT_ENCODING_KEY ) ) ,
133- ) {
134- match ContentEncoding :: try_from ( value ) {
135- Ok ( encoding ) => {
136- metadata . content_encoding = Some ( encoding ) ;
137- } ,
138- Err ( e ) => {
139- errors . push ( anyhow ! ( "Invalid Document Content Encoding: {e}" ) ) ;
140- } ,
141- }
142- } else {
116+ let content_encoding = cose_protected_header_find ( protected , |key| matches ! ( key , coset :: Label :: Text ( label ) if label . eq_ignore_ascii_case ( CONTENT_ENCODING_KEY ) ) ,
117+ )
118+ . and_then ( |value| {
119+ ContentEncoding :: try_from ( value ) . map_or_else (
120+ |e| {
121+ errors . push ( anyhow ! ( "Invalid Document Content Encoding: {e}" ) ) ;
122+ None
123+ } ,
124+ Some ,
125+ )
126+ } ) ;
127+
128+ if content_encoding . is_none ( ) {
143129 errors. push ( anyhow ! (
144- "Invalid COSE document protected header '{CONTENT_ENCODING_KEY}' is missing "
130+ "Invalid COSE protected header, missing Content-Encoding field "
145131 ) ) ;
146132 }
147133
148- if let Some ( doc_type) = cose_protected_header_find ( protected, |key| {
134+ let doc_type = cose_protected_header_find ( protected, |key| {
149135 key == & coset:: Label :: Text ( "type" . to_string ( ) )
150- } ) {
151- match UuidV4 :: try_from ( doc_type) {
152- Ok ( doc_type_uuid) => {
153- metadata. doc_type = doc_type_uuid. into ( ) ;
154- } ,
155- Err ( e) => {
136+ } )
137+ . and_then ( |value| {
138+ UuidV4 :: try_from ( value) . map_or_else (
139+ |e| {
156140 errors. push ( anyhow ! ( "Document `type` is invalid: {e}" ) ) ;
141+ None
157142 } ,
158- }
159- } else {
143+ Some ,
144+ )
145+ } ) ;
146+
147+ if doc_type. is_none ( ) {
160148 errors. push ( anyhow ! (
161149 "Invalid COSE protected header, missing `type` field"
162150 ) ) ;
163151 }
164152
165- match cose_protected_header_find ( protected, |key| {
153+ let id = cose_protected_header_find ( protected, |key| {
166154 key == & coset:: Label :: Text ( "id" . to_string ( ) )
167- } ) {
168- Some ( doc_id) => {
169- match UuidV7 :: try_from ( doc_id) {
170- Ok ( doc_id_uuid) => {
171- metadata. id = doc_id_uuid. into ( ) ;
172- } ,
173- Err ( e) => {
174- errors. push ( anyhow ! ( "Document `id` is invalid: {e}" ) ) ;
175- } ,
176- }
177- } ,
178- None => errors. push ( anyhow ! ( "Invalid COSE protected header, missing `id` field" ) ) ,
179- } ;
155+ } )
156+ . and_then ( |value| {
157+ UuidV7 :: try_from ( value) . map_or_else (
158+ |e| {
159+ errors. push ( anyhow ! ( "Document `id` is invalid: {e}" ) ) ;
160+ None
161+ } ,
162+ Some ,
163+ )
164+ } ) ;
180165
181- match cose_protected_header_find ( protected, |key| {
166+ if id. is_none ( ) {
167+ errors. push ( anyhow ! ( "Invalid COSE protected header, missing `id` field" ) ) ;
168+ }
169+
170+ let ver = cose_protected_header_find ( protected, |key| {
182171 key == & coset:: Label :: Text ( "ver" . to_string ( ) )
183- } ) {
184- Some ( doc_ver) => {
185- match UuidV7 :: try_from ( doc_ver) {
186- Ok ( doc_ver_uuid) => {
187- if doc_ver_uuid. uuid ( ) < metadata. id . uuid ( ) {
188- errors. push ( anyhow ! (
189- "Document Version {doc_ver_uuid} cannot be smaller than Document ID {}" , metadata. id
190- ) ) ;
191- } else {
192- metadata. ver = doc_ver_uuid. into ( ) ;
193- }
194- } ,
195- Err ( e) => {
196- errors. push ( anyhow ! (
197- "Invalid COSE protected header `ver` field, err: {e}"
198- ) ) ;
199- } ,
200- }
201- } ,
202- None => {
203- errors. push ( anyhow ! (
204- "Invalid COSE protected header, missing `ver` field"
205- ) ) ;
206- } ,
172+ } )
173+ . and_then ( |value| {
174+ UuidV7 :: try_from ( value) . map_or_else (
175+ |e| {
176+ errors. push ( anyhow ! ( "Document `ver` is invalid: {e}" ) ) ;
177+ None
178+ } ,
179+ Some ,
180+ )
181+ } ) ;
182+
183+ if ver. is_none ( ) {
184+ errors. push ( anyhow ! (
185+ "Invalid COSE protected header, missing `ver` field"
186+ ) ) ;
207187 }
208188
209- match AdditionalFields :: try_from ( protected) {
210- Ok ( extra) => metadata. extra = extra,
211- Err ( e) => errors. extend ( e) ,
212- } ;
189+ let extra = AdditionalFields :: try_from ( protected) . map_or_else (
190+ |e| {
191+ errors. extend ( e) ;
192+ None
193+ } ,
194+ Some ,
195+ ) ;
196+
197+ match ( content_type, content_encoding, id, doc_type, ver, extra) {
198+ (
199+ Some ( content_type) ,
200+ content_encoding,
201+ Some ( id) ,
202+ Some ( doc_type) ,
203+ Some ( ver) ,
204+ Some ( extra) ,
205+ ) => {
206+ if ver < id {
207+ errors. push ( anyhow ! (
208+ "Document Version {ver} cannot be smaller than Document ID {id}" ,
209+ ) ) ;
210+ return Err ( crate :: error:: Error ( errors) ) ;
211+ }
213212
214- if errors. is_empty ( ) {
215- Ok ( metadata)
216- } else {
217- Err ( errors. into ( ) )
213+ Ok ( Self {
214+ doc_type : doc_type. into ( ) ,
215+ id : id. into ( ) ,
216+ ver : ver. into ( ) ,
217+ content_encoding,
218+ content_type,
219+ extra,
220+ } )
221+ } ,
222+ _ => Err ( crate :: error:: Error ( errors) ) ,
218223 }
219224 }
220225}
0 commit comments