Skip to content

Commit 3b5b47a

Browse files
committed
feat(rust/signed-doc): generate content encoding rules from macro
1 parent 2607d4d commit 3b5b47a

File tree

6 files changed

+64
-16
lines changed

6 files changed

+64
-16
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//! `signed_doc.json` headers content encoding field JSON definition
2+
//! Content Encoding
3+
4+
use crate::is_required::IsRequired;
5+
6+
#[derive(serde::Deserialize)]
7+
pub struct ContentEncoding {
8+
pub required: IsRequired,
9+
pub value: Option<Vec<String>>,
10+
}

rust/catalyst-signed-doc-spec/src/headers/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! 'headers' field definition
22
3+
pub mod content_encoding;
34
pub mod content_type;
45

56
/// Document's metadata fields definition
@@ -8,4 +9,6 @@ pub mod content_type;
89
pub struct Headers {
910
#[serde(rename = "content type")]
1011
pub content_type: content_type::ContentType,
12+
#[serde(rename = "content-encoding")]
13+
pub content_encoding: content_encoding::ContentEncoding,
1114
}

rust/signed_doc/src/validator/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn proposal_rule() -> Rules {
4242
exp: ContentType::Json,
4343
},
4444
content_encoding: ContentEncodingRule::Specified {
45-
exp: ContentEncoding::Brotli,
45+
exp: vec![ContentEncoding::Brotli],
4646
optional: false,
4747
},
4848
template: TemplateRule::Specified {
@@ -81,7 +81,7 @@ fn proposal_comment_rule() -> Rules {
8181
exp: ContentType::Json,
8282
},
8383
content_encoding: ContentEncodingRule::Specified {
84-
exp: ContentEncoding::Brotli,
84+
exp: vec![ContentEncoding::Brotli],
8585
optional: false,
8686
},
8787
template: TemplateRule::Specified {
@@ -138,7 +138,7 @@ fn proposal_submission_action_rule() -> Rules {
138138
exp: ContentType::Json,
139139
},
140140
content_encoding: ContentEncodingRule::Specified {
141-
exp: ContentEncoding::Brotli,
141+
exp: vec![ContentEncoding::Brotli],
142142
optional: false,
143143
},
144144
template: TemplateRule::NotSpecified,

rust/signed_doc/src/validator/rules/content_encoding.rs

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
//! `content-encoding` rule type impl.
22
3+
use std::string::ToString;
4+
5+
use catalyst_signed_doc_spec::is_required::IsRequired;
6+
37
use 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

2023
impl 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());

rust/signed_doc/src/validator/rules/content_type.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ pub(crate) enum ContentTypeRule {
1111
exp: ContentType,
1212
},
1313
/// Content Type field must not be present in the document.
14-
#[allow(dead_code)]
1514
NotSpecified,
1615
}
1716

rust/signed_doc/src/validator/rules/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ impl Rules {
122122
id: IdRule,
123123
ver: VerRule,
124124
content_type: ContentTypeRule::new(&doc_spec.headers.content_type)?,
125-
content_encoding: ContentEncodingRule::NotSpecified,
125+
content_encoding: ContentEncodingRule::new(&doc_spec.headers.content_encoding)?,
126126
template: TemplateRule::NotSpecified,
127127
parameters: ParametersRule::NotSpecified,
128128
doc_ref: RefRule::new(&spec.docs, &doc_spec.metadata.doc_ref)?,

0 commit comments

Comments
 (0)