11//! `content-encoding` rule type impl.
22
3+ use catalyst_signed_doc_spec:: is_required:: IsRequired ;
4+
35use crate :: { metadata:: ContentEncoding , CatalystSignedDocument } ;
46
57/// `content-encoding` field validation rule.
@@ -8,16 +10,49 @@ pub(crate) enum ContentEncodingRule {
810 /// Content Encoding field is optionally present in the document.
911 Specified {
1012 /// expected `content-encoding` field.
11- exp : ContentEncoding ,
13+ exp : Vec < ContentEncoding > ,
1214 /// optional flag for the `content-encoding` field.
1315 optional : bool ,
1416 } ,
1517 /// Content Encoding field must not be present in the document.
16- #[ allow( dead_code) ]
1718 NotSpecified ,
1819}
1920
2021impl ContentEncodingRule {
22+ pub ( crate ) fn new (
23+ spec : & catalyst_signed_doc_spec:: headers:: content_encoding:: ContentEncoding
24+ ) -> anyhow:: Result < Self > {
25+ if let IsRequired :: Excluded = spec. required {
26+ anyhow:: ensure!(
27+ spec. value. is_none( ) ,
28+ "'content type' field must not exist when 'required' is 'excluded'"
29+ ) ;
30+ return Ok ( Self :: NotSpecified ) ;
31+ }
32+
33+ if let IsRequired :: Yes = spec. required {
34+ anyhow:: ensure!(
35+ spec. value. is_some( ) ,
36+ "'content-encoding' field must have value when 'required' is 'yes'"
37+ ) ;
38+ }
39+
40+ let optional = IsRequired :: Optional == spec. required ;
41+
42+ let mut exp = Vec :: new ( ) ;
43+ for encoding in spec
44+ . value
45+ . as_ref ( )
46+ . ok_or ( anyhow:: anyhow!( "'content-encoding' field must have value " ) ) ?
47+ . iter ( )
48+ . cloned ( )
49+ {
50+ exp. push ( encoding. parse ( ) ?) ;
51+ }
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 ( |e| e. 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