11//! `content-encoding` rule type impl.
22
3+ use std:: string:: ToString ;
4+
5+ use catalyst_signed_doc_spec:: is_required:: IsRequired ;
6+
37use crate :: { metadata:: ContentEncoding , CatalystSignedDocument } ;
48
59/// `content-encoding` field validation rule.
@@ -8,16 +12,47 @@ pub(crate) enum ContentEncodingRule {
812 /// Content Encoding field is optionally present in the document.
913 Specified {
1014 /// expected `content-encoding` field.
11- exp : ContentEncoding ,
15+ exp : Vec < ContentEncoding > ,
1216 /// optional flag for the `content-encoding` field.
1317 optional : bool ,
1418 } ,
1519 /// Content Encoding field must not be present in the document.
16- #[ allow( dead_code) ]
1720 NotSpecified ,
1821}
1922
2023impl ContentEncodingRule {
24+ /// Create a new rule from specs.
25+ pub ( crate ) fn new (
26+ spec : & catalyst_signed_doc_spec:: headers:: content_encoding:: ContentEncoding
27+ ) -> anyhow:: Result < Self > {
28+ if let IsRequired :: Excluded = spec. required {
29+ anyhow:: ensure!(
30+ spec. value. is_none( ) ,
31+ "'content type' field must not exist when 'required' is 'excluded'"
32+ ) ;
33+ return Ok ( Self :: NotSpecified ) ;
34+ }
35+
36+ if let IsRequired :: Yes = spec. required {
37+ anyhow:: ensure!(
38+ spec. value. is_some( ) ,
39+ "'content-encoding' field must have value when 'required' is 'yes'"
40+ ) ;
41+ }
42+
43+ let optional = IsRequired :: Optional == spec. required ;
44+
45+ let exp = spec
46+ . value
47+ . as_ref ( )
48+ . ok_or ( anyhow:: anyhow!( "'content-encoding' field must have value " ) ) ?
49+ . iter ( )
50+ . flat_map ( |encoding| encoding. parse ( ) )
51+ . collect ( ) ;
52+
53+ Ok ( Self :: Specified { exp, optional } )
54+ }
55+
2156 /// Field validation rule
2257 #[ allow( clippy:: unused_async) ]
2358 pub ( crate ) async fn check (
@@ -40,23 +75,24 @@ impl ContentEncodingRule {
4075 } ,
4176 Self :: Specified { exp, optional } => {
4277 if let Some ( content_encoding) = doc. doc_content_encoding ( ) {
43- if content_encoding != * exp {
78+ if ! exp. contains ( & content_encoding ) {
4479 doc. report ( ) . invalid_value (
4580 "content-encoding" ,
4681 content_encoding. to_string ( ) . as_str ( ) ,
47- exp. to_string ( ) . as_str ( ) ,
48- "Invalid Document content-encoding value" ,
82+ & exp. iter ( )
83+ . map ( ToString :: to_string)
84+ . collect :: < Vec < _ > > ( )
85+ . join ( ", " ) ,
86+ "Invalid document content-encoding value" ,
4987 ) ;
5088 return Ok ( false ) ;
5189 }
5290 if content_encoding. decode ( doc. encoded_content ( ) ) . is_err ( ) {
5391 doc. report ( ) . invalid_value (
5492 "payload" ,
5593 & hex:: encode ( doc. encoded_content ( ) ) ,
56- & format ! (
57- "Document content (payload) must decodable by the set content encoding type: {content_encoding}"
58- ) ,
59- "Invalid Document content value" ,
94+ content_encoding. to_string ( ) . as_str ( ) ,
95+ "Document content is not decodable with the expected content-encoding" ,
6096 ) ;
6197 return Ok ( false ) ;
6298 }
@@ -83,7 +119,7 @@ mod tests {
83119 let content_encoding = ContentEncoding :: Brotli ;
84120
85121 let rule = ContentEncodingRule :: Specified {
86- exp : content_encoding,
122+ exp : vec ! [ content_encoding] ,
87123 optional : true ,
88124 } ;
89125
@@ -103,7 +139,7 @@ mod tests {
103139 assert ! ( rule. check( & doc) . await . unwrap( ) ) ;
104140
105141 let rule = ContentEncodingRule :: Specified {
106- exp : content_encoding,
142+ exp : vec ! [ content_encoding] ,
107143 optional : false ,
108144 } ;
109145 assert ! ( !rule. check( & doc) . await . unwrap( ) ) ;
0 commit comments