Skip to content

Commit af7fc4b

Browse files
authored
feat(rust/signed-doc): Added more decoding test cases, cleaned up DecodeContext (#401)
* fix signed_doc_with_random_header_field_case * add signed_doc_with_non_empty_unprotected_headers, signed_doc_with_signatures_non_empty_unprotected_headers test cases * refactor DecodeContext * wip * add new test cases * wip * fix clippy
1 parent b861937 commit af7fc4b

File tree

10 files changed

+371
-131
lines changed

10 files changed

+371
-131
lines changed

rust/signed_doc/bins/mk_signed_doc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ fn save_signed_doc(signed_doc: CatalystSignedDocument, path: &PathBuf) -> anyhow
129129
}
130130

131131
fn signed_doc_from_bytes(cose_bytes: &[u8]) -> anyhow::Result<CatalystSignedDocument> {
132-
minicbor::decode(cose_bytes).context("Invalid Catalyst Document")
132+
cose_bytes.try_into().context("Invalid Catalyst Document")
133133
}
134134

135135
fn load_json_from_file<T>(path: &PathBuf) -> anyhow::Result<T>

rust/signed_doc/src/decode_context.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
use catalyst_types::problem_report::ProblemReport;
44

55
/// Compatibility policy
6-
#[allow(dead_code)]
76
#[derive(Copy, Clone)]
8-
pub(crate) enum CompatibilityPolicy {
7+
pub enum CompatibilityPolicy {
98
/// Silently allow obsoleted type conversions or non deterministic encoding.
109
Accept,
1110
/// Allow but log Warnings for all obsoleted type conversions or non deterministic
@@ -17,9 +16,35 @@ pub(crate) enum CompatibilityPolicy {
1716
}
1817

1918
/// A context use to pass to decoder.
20-
pub(crate) struct DecodeContext<'r> {
19+
pub(crate) struct DecodeContext {
2120
/// Compatibility policy.
22-
pub compatibility_policy: CompatibilityPolicy,
21+
compatibility_policy: CompatibilityPolicy,
2322
/// Problem report.
24-
pub report: &'r mut ProblemReport,
23+
report: ProblemReport,
24+
}
25+
26+
impl DecodeContext {
27+
/// Creates a new instance of the `DecodeContext`
28+
pub(crate) fn new(compatibility_policy: CompatibilityPolicy, report: ProblemReport) -> Self {
29+
Self {
30+
compatibility_policy,
31+
report,
32+
}
33+
}
34+
35+
/// Returns `CompatibilityPolicy`
36+
pub(crate) fn policy(&self) -> &CompatibilityPolicy {
37+
&self.compatibility_policy
38+
}
39+
40+
/// Returns `ProblemReport`
41+
pub(crate) fn report(&mut self) -> &mut ProblemReport {
42+
&mut self.report
43+
}
44+
45+
/// Consuming the current `DecodeContext` by returning the underlying `ProblemReport`
46+
/// instance
47+
pub(crate) fn into_report(self) -> ProblemReport {
48+
self.report
49+
}
2550
}

rust/signed_doc/src/lib.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
mod builder;
44
mod content;
5-
mod decode_context;
5+
pub mod decode_context;
66
pub mod doc_types;
77
mod metadata;
88
pub mod providers;
@@ -208,13 +208,12 @@ impl CatalystSignedDocument {
208208
}
209209
}
210210

211-
impl Decode<'_, ()> for CatalystSignedDocument {
212-
fn decode(d: &mut Decoder<'_>, _ctx: &mut ()) -> Result<Self, decode::Error> {
213-
let mut report = ProblemReport::new("Catalyst Signed Document Decoding");
214-
let mut ctx = DecodeContext {
215-
compatibility_policy: CompatibilityPolicy::Accept,
216-
report: &mut report,
217-
};
211+
impl Decode<'_, CompatibilityPolicy> for CatalystSignedDocument {
212+
fn decode(d: &mut Decoder<'_>, ctx: &mut CompatibilityPolicy) -> Result<Self, decode::Error> {
213+
let mut ctx = DecodeContext::new(
214+
*ctx,
215+
ProblemReport::new("Catalyst Signed Document Decoding"),
216+
);
218217

219218
let p = d.position();
220219
if let Ok(tag) = d.tag() {
@@ -246,7 +245,7 @@ impl Decode<'_, ()> for CatalystSignedDocument {
246245
)?
247246
.into_iter();
248247
if map.next().is_some() {
249-
ctx.report.unknown_field(
248+
ctx.report().unknown_field(
250249
"unprotected headers",
251250
"non empty unprotected headers",
252251
"COSE unprotected headers must be empty",
@@ -260,7 +259,7 @@ impl Decode<'_, ()> for CatalystSignedDocument {
260259
metadata,
261260
content,
262261
signatures,
263-
report,
262+
report: ctx.into_report(),
264263
}
265264
.into())
266265
}
@@ -294,7 +293,10 @@ impl TryFrom<&[u8]> for CatalystSignedDocument {
294293
type Error = anyhow::Error;
295294

296295
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
297-
Ok(minicbor::decode(value)?)
296+
Ok(minicbor::decode_with(
297+
value,
298+
&mut CompatibilityPolicy::Accept,
299+
)?)
298300
}
299301
}
300302

rust/signed_doc/src/metadata/doc_type.rs

Lines changed: 26 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl Display for DocType {
144144
// document_type = [ 1* uuid_v4 ]
145145
// ; UUIDv4
146146
// uuid_v4 = #6.37(bytes .size 16)
147-
impl Decode<'_, DecodeContext<'_>> for DocType {
147+
impl Decode<'_, DecodeContext> for DocType {
148148
fn decode(
149149
d: &mut Decoder, decode_context: &mut DecodeContext,
150150
) -> Result<Self, minicbor::decode::Error> {
@@ -155,15 +155,15 @@ impl Decode<'_, DecodeContext<'_>> for DocType {
155155
minicbor::data::Type::Array => {
156156
let len = d.array()?.ok_or_else(|| {
157157
decode_context
158-
.report
158+
.report()
159159
.other("Unable to decode array length", CONTEXT);
160160
minicbor::decode::Error::message(format!(
161161
"{CONTEXT}: Unable to decode array length"
162162
))
163163
})?;
164164

165165
if len == 0 {
166-
decode_context.report.invalid_value(
166+
decode_context.report().invalid_value(
167167
"array length",
168168
"0",
169169
"must contain at least one UUIDv4",
@@ -180,7 +180,7 @@ impl Decode<'_, DecodeContext<'_>> for DocType {
180180
.map(Self)
181181
.map_err(|e| {
182182
decode_context
183-
.report
183+
.report()
184184
.other(&format!("Invalid UUIDv4 in array: {e}"), CONTEXT);
185185
minicbor::decode::Error::message(format!(
186186
"{CONTEXT}: Invalid UUIDv4 in array: {e}"
@@ -189,18 +189,15 @@ impl Decode<'_, DecodeContext<'_>> for DocType {
189189
},
190190
minicbor::data::Type::Tag => {
191191
// Handle single tagged UUID
192-
match decode_context.compatibility_policy {
192+
match decode_context.policy() {
193193
CompatibilityPolicy::Accept | CompatibilityPolicy::Warn => {
194-
if matches!(
195-
decode_context.compatibility_policy,
196-
CompatibilityPolicy::Warn
197-
) {
194+
if matches!(decode_context.policy(), CompatibilityPolicy::Warn) {
198195
warn!("{CONTEXT}: Conversion of document type single UUID to type DocType");
199196
}
200197

201198
let uuid = parse_uuid(d).map_err(|e| {
202199
let msg = format!("Cannot decode single UUIDv4: {e}");
203-
decode_context.report.invalid_value(
200+
decode_context.report().invalid_value(
204201
"Decode single UUIDv4",
205202
&e.to_string(),
206203
&msg,
@@ -214,15 +211,15 @@ impl Decode<'_, DecodeContext<'_>> for DocType {
214211

215212
CompatibilityPolicy::Fail => {
216213
let msg = "Conversion of document type single UUID to type DocType is not allowed";
217-
decode_context.report.other(msg, CONTEXT);
214+
decode_context.report().other(msg, CONTEXT);
218215
Err(minicbor::decode::Error::message(format!(
219216
"{CONTEXT}: {msg}"
220217
)))
221218
},
222219
}
223220
},
224221
other => {
225-
decode_context.report.invalid_value(
222+
decode_context.report().invalid_value(
226223
"decoding type",
227224
&format!("{other:?}"),
228225
"array or tag cbor",
@@ -342,49 +339,45 @@ mod tests {
342339
fn test_empty_doc_type_cbor_decode() {
343340
assert!(<DocType as TryFrom<Vec<UuidV4>>>::try_from(vec![]).is_err());
344341

345-
let mut report = ProblemReport::new("Test empty doc type");
346-
let mut decoded_context = DecodeContext {
347-
compatibility_policy: CompatibilityPolicy::Accept,
348-
report: &mut report,
349-
};
342+
let mut decoded_context = DecodeContext::new(
343+
CompatibilityPolicy::Accept,
344+
ProblemReport::new("Test empty doc type"),
345+
);
350346
let mut decoder = Decoder::new(&[]);
351347
assert!(DocType::decode(&mut decoder, &mut decoded_context).is_err());
352348
}
353349

354350
#[test]
355351
fn test_single_uuid_doc_type_fail_policy_cbor_decode() {
356-
let mut report = ProblemReport::new("Test single uuid doc type - fail");
357352
let data = hex::decode(PSA).unwrap();
358353
let decoder = Decoder::new(&data);
359-
let mut decoded_context = DecodeContext {
360-
compatibility_policy: CompatibilityPolicy::Fail,
361-
report: &mut report,
362-
};
354+
let mut decoded_context = DecodeContext::new(
355+
CompatibilityPolicy::Fail,
356+
ProblemReport::new("Test single uuid doc type - fail"),
357+
);
363358
assert!(DocType::decode(&mut decoder.clone(), &mut decoded_context).is_err());
364359
}
365360

366361
#[test]
367362
fn test_single_uuid_doc_type_warn_policy_cbor_decode() {
368-
let mut report = ProblemReport::new("Test single uuid doc type - warn");
369363
let data = hex::decode(PSA).unwrap();
370364
let decoder = Decoder::new(&data);
371-
let mut decoded_context = DecodeContext {
372-
compatibility_policy: CompatibilityPolicy::Warn,
373-
report: &mut report,
374-
};
365+
let mut decoded_context = DecodeContext::new(
366+
CompatibilityPolicy::Warn,
367+
ProblemReport::new("Test single uuid doc type - warn"),
368+
);
375369
let decoded_doc_type = DocType::decode(&mut decoder.clone(), &mut decoded_context).unwrap();
376370
assert_eq!(decoded_doc_type.doc_types().len(), 3);
377371
}
378372

379373
#[test]
380374
fn test_single_uuid_doc_type_accept_policy_cbor_decode() {
381-
let mut report = ProblemReport::new("Test single uuid doc type - accept");
382375
let data = hex::decode(PSA).unwrap();
383376
let decoder = Decoder::new(&data);
384-
let mut decoded_context = DecodeContext {
385-
compatibility_policy: CompatibilityPolicy::Accept,
386-
report: &mut report,
387-
};
377+
let mut decoded_context = DecodeContext::new(
378+
CompatibilityPolicy::Accept,
379+
ProblemReport::new("Test single uuid doc type - accept"),
380+
);
388381
let decoded_doc_type = DocType::decode(&mut decoder.clone(), &mut decoded_context).unwrap();
389382
assert_eq!(decoded_doc_type.doc_types().len(), 3);
390383
}
@@ -398,10 +391,7 @@ mod tests {
398391
let mut encoder = Encoder::new(&mut buffer);
399392
doc_type_list.encode(&mut encoder, &mut report).unwrap();
400393
let mut decoder = Decoder::new(&buffer);
401-
let mut decoded_context = DecodeContext {
402-
compatibility_policy: CompatibilityPolicy::Accept,
403-
report: &mut report.clone(),
404-
};
394+
let mut decoded_context = DecodeContext::new(CompatibilityPolicy::Accept, report);
405395
let decoded_doc_type = DocType::decode(&mut decoder, &mut decoded_context).unwrap();
406396
assert_eq!(decoded_doc_type, doc_type_list);
407397
}

rust/signed_doc/src/metadata/document_refs/doc_ref.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,21 +62,21 @@ impl Display for DocumentRef {
6262
}
6363
}
6464

65-
impl Decode<'_, DecodeContext<'_>> for DocumentRef {
65+
impl Decode<'_, DecodeContext> for DocumentRef {
6666
fn decode(
67-
d: &mut minicbor::Decoder<'_>, decode_context: &mut DecodeContext<'_>,
67+
d: &mut minicbor::Decoder<'_>, decode_context: &mut DecodeContext,
6868
) -> Result<Self, minicbor::decode::Error> {
6969
const CONTEXT: &str = "DocumentRef decoding";
7070
let parse_uuid = |d: &mut Decoder| UuidV7::decode(d, &mut CborContext::Tagged);
7171

7272
let arr = d.array()?.ok_or_else(|| {
7373
decode_context
74-
.report
74+
.report()
7575
.other("Unable to decode array length", CONTEXT);
7676
minicbor::decode::Error::message(format!("{CONTEXT}: Unable to decode array length"))
7777
})?;
7878
if arr != DOC_REF_ARR_ITEM {
79-
decode_context.report.invalid_value(
79+
decode_context.report().invalid_value(
8080
"Array length",
8181
&arr.to_string(),
8282
&DOC_REF_ARR_ITEM.to_string(),
@@ -88,21 +88,21 @@ impl Decode<'_, DecodeContext<'_>> for DocumentRef {
8888
}
8989
let id = parse_uuid(d).map_err(|e| {
9090
decode_context
91-
.report
91+
.report()
9292
.other(&format!("Invalid ID UUIDv7: {e}"), CONTEXT);
9393
e.with_message("Invalid ID UUIDv7")
9494
})?;
9595

9696
let ver = parse_uuid(d).map_err(|e| {
9797
decode_context
98-
.report
98+
.report()
9999
.other(&format!("Invalid Ver UUIDv7: {e}"), CONTEXT);
100100
e.with_message("Invalid Ver UUIDv7")
101101
})?;
102102

103-
let locator = DocLocator::decode(d, decode_context.report).map_err(|e| {
103+
let locator = DocLocator::decode(d, decode_context.report()).map_err(|e| {
104104
decode_context
105-
.report
105+
.report()
106106
.other(&format!("Failed to decode locator {e}"), CONTEXT);
107107
e.with_message("Failed to decode locator")
108108
})?;

0 commit comments

Comments
 (0)