• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

input-output-hk / catalyst-libs / 21514247239

30 Jan 2026 11:27AM UTC coverage: 69.748% (+0.02%) from 69.732%
21514247239

Pull #827

github

web-flow
Merge ead8131a4 into 8e0bee52d
Pull Request #827: chore(rust/signed-doc): Remove the boolean flag from the content encoding rule

30 of 30 new or added lines in 1 file covered. (100.0%)

2 existing lines in 2 files now uncovered.

16870 of 24187 relevant lines covered (69.75%)

2240.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.08
/rust/signed_doc/src/validator/rules/content_encoding.rs
1
//! `content-encoding` rule type impl.
2

3
use std::string::ToString;
4

5
use catalyst_signed_doc_spec::is_required::IsRequired;
6

7
use crate::{
8
    CatalystSignedDocument, metadata::ContentEncoding, providers::Provider,
9
    validator::CatalystSignedDocumentValidationRule,
10
};
11

12
/// `content-encoding` field validation rule.
13
#[derive(Debug)]
14
pub(crate) enum ContentEncodingRule {
15
    /// Content Encoding field is optionally present in the document.
16
    Specified {
17
        /// expected `content-encoding` field.
18
        exp: Vec<ContentEncoding>,
19
        /// optional flag for the `content-encoding` field.
20
        optional: bool,
21
    },
22
    /// Content Encoding field must not be present in the document.
23
    NotSpecified,
24
}
25

26
impl CatalystSignedDocumentValidationRule for ContentEncodingRule {
27
    fn check(
150✔
28
        &self,
150✔
29
        doc: &CatalystSignedDocument,
150✔
30
        _provider: &dyn Provider,
150✔
31
    ) -> anyhow::Result<bool> {
150✔
32
        self.check_inner(doc);
150✔
33
        Ok(!doc.report().is_problematic())
150✔
34
    }
150✔
35
}
36

37
impl ContentEncodingRule {
38
    /// Create a new rule from specs.
39
    pub(crate) fn new(
3,192✔
40
        spec: &catalyst_signed_doc_spec::headers::content_encoding::ContentEncoding
3,192✔
41
    ) -> anyhow::Result<Self> {
3,192✔
42
        if let IsRequired::Excluded = spec.required {
3,192✔
43
            anyhow::ensure!(
×
44
                spec.value.is_none(),
×
45
                "'content type' field must not exist when 'required' is 'excluded'"
×
46
            );
47
            return Ok(Self::NotSpecified);
×
48
        }
3,192✔
49

50
        let optional = IsRequired::Optional == spec.required;
3,192✔
51

52
        let exp = spec
3,192✔
53
            .value
3,192✔
54
            .as_ref()
3,192✔
55
            .ok_or(anyhow::anyhow!("'content-encoding' field must have value "))?
3,192✔
56
            .iter()
3,192✔
57
            .flat_map(|encoding| encoding.parse())
3,192✔
58
            .collect();
3,192✔
59

60
        Ok(Self::Specified { exp, optional })
3,192✔
61
    }
3,192✔
62

63
    /// Field validation rule
64
    fn check_inner(
156✔
65
        &self,
156✔
66
        doc: &CatalystSignedDocument,
156✔
67
    ) {
156✔
68
        let context = "Content Encoding Rule check";
156✔
69
        match self {
156✔
70
            Self::NotSpecified => {
71
                if let Some(content_encoding) = doc.doc_content_encoding() {
2✔
72
                    doc.report().unknown_field(
1✔
73
                        "content-encoding",
1✔
74
                        &content_encoding.to_string(),
1✔
75
                        &format!(
1✔
76
                            "{context}, document does not expect to have a content-encoding field"
1✔
77
                        ),
1✔
78
                    );
1✔
79
                }
1✔
80
            },
81
            Self::Specified { exp, optional } => {
154✔
82
                if let Some(content_encoding) = doc.doc_content_encoding() {
154✔
83
                    if !exp.contains(&content_encoding) {
133✔
84
                        doc.report().invalid_value(
×
85
                            "content-encoding",
×
86
                            content_encoding.to_string().as_str(),
×
87
                            &exp.iter()
×
88
                                .map(ToString::to_string)
×
89
                                .collect::<Vec<_>>()
×
90
                                .join(", "),
×
91
                            "Invalid document content-encoding value",
×
UNCOV
92
                        );
×
93
                    }
133✔
94
                    if content_encoding.decode(doc.encoded_content()).is_err() {
133✔
95
                        doc.report().invalid_value(
21✔
96
                            "payload",
21✔
97
                            &hex::encode(doc.encoded_content()),
21✔
98
                            content_encoding.to_string().as_str(),
21✔
99
                            "Document content is not decodable with the expected content-encoding",
21✔
100
                        );
21✔
101
                    }
112✔
102
                } else if !optional {
21✔
103
                    doc.report().missing_field(
1✔
104
                        "content-encoding",
1✔
105
                        "Document must have a content-encoding field",
1✔
106
                    );
1✔
107
                }
20✔
108
            },
109
        }
110
    }
156✔
111
}
112

113
#[cfg(test)]
114
mod tests {
115
    use super::*;
116
    use crate::{builder::tests::Builder, metadata::SupportedField};
117

118
    #[test]
119
    fn content_encoding_is_specified_rule_test() {
1✔
120
        let content_encoding = ContentEncoding::Brotli;
1✔
121

122
        let rule = ContentEncodingRule::Specified {
1✔
123
            exp: vec![content_encoding],
1✔
124
            optional: true,
1✔
125
        };
1✔
126

127
        let doc = Builder::with_required_fields()
1✔
128
            .with_metadata_field(SupportedField::ContentEncoding(content_encoding))
1✔
129
            .with_content(content_encoding.encode(&[1, 2, 3]).unwrap())
1✔
130
            .build();
1✔
131
        rule.check_inner(&doc);
1✔
132
        assert!(!doc.report().is_problematic());
1✔
133

134
        // empty content (empty bytes) could not be brotli decoded
135
        let doc = Builder::with_required_fields()
1✔
136
            .with_metadata_field(SupportedField::ContentEncoding(content_encoding))
1✔
137
            .build();
1✔
138
        rule.check_inner(&doc);
1✔
139
        let report = format!("{:?}", doc.report());
1✔
140
        println!("{report}");
1✔
141
        assert!(doc.report().is_problematic());
1✔
142
        assert!(
1✔
143
            report.contains("Document content is not decodable with the expected content-encoding")
1✔
144
        );
145

146
        let doc = Builder::with_required_fields().build();
1✔
147
        rule.check_inner(&doc);
1✔
148
        assert!(!doc.report().is_problematic());
1✔
149

150
        let rule = ContentEncodingRule::Specified {
1✔
151
            exp: vec![content_encoding],
1✔
152
            optional: false,
1✔
153
        };
1✔
154
        rule.check_inner(&doc);
1✔
155
        let report = format!("{:?}", doc.report());
1✔
156
        println!("{report}");
1✔
157
        assert!(doc.report().is_problematic());
1✔
158
        assert!(report.contains("Document must have a content-encoding field"));
1✔
159
    }
1✔
160

161
    #[test]
162
    fn content_encoding_is_not_specified_rule_test() {
1✔
163
        let content_encoding = ContentEncoding::Brotli;
1✔
164

165
        let rule = ContentEncodingRule::NotSpecified;
1✔
166

167
        // With Brotli content encoding
168
        let doc = Builder::with_required_fields()
1✔
169
            .with_metadata_field(SupportedField::ContentEncoding(content_encoding))
1✔
170
            .build();
1✔
171
        rule.check_inner(&doc);
1✔
172
        let report = format!("{:?}", doc.report());
1✔
173
        println!("{report}");
1✔
174
        assert!(doc.report().is_problematic());
1✔
175
        assert!(report.contains("document does not expect to have a content-encoding field"));
1✔
176

177
        // No content encoding
178
        let doc = Builder::with_required_fields().build();
1✔
179
        rule.check_inner(&doc);
1✔
180
        assert!(!doc.report().is_problematic());
1✔
181
    }
1✔
182
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc