Skip to content

Commit

Permalink
Optional array fields with preserve-encodings=true
Browse files Browse the repository at this point in the history
  • Loading branch information
rooooooooob committed Aug 2, 2023
1 parent 9a14093 commit 71f5cce
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 18 deletions.
63 changes: 46 additions & 17 deletions src/generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4408,9 +4408,8 @@ fn generate_array_struct_deserialization(
gen_scope.dont_generate_deserialize(
name,
format!(
"Array struct with potentially-ambiguous optional field {}: {}",
field.name,
field.rust_type.for_rust_member(types, false, cli)
"Array struct with potentially-ambiguous optional field {}: {:?}",
field.name, field.rust_type,
),
);
}
Expand Down Expand Up @@ -4463,6 +4462,39 @@ fn generate_array_struct_deserialization(
let type_check_block = Block::new(format!("{before}{type_check_cond}"));
let mut type_check_else = Block::new("else");
if cli.annotate_fields {
let enc_fields = if cli.preserve_encodings {
let resolved_rust_type = field.rust_type.clone().resolve_aliases();
assert!(
!resolved_rust_type.is_fixed_value(),
"https://github.com/dcSpark/cddl-codegen/issues/205"
);
encoding_fields(types, &field.name, &resolved_rust_type, false, cli)
} else {
vec![]
};
let (some_map, defaults) = if !enc_fields.is_empty() {
let enc_names_str = enc_fields
.iter()
.map(|enc| enc.field_name.clone())
.collect::<Vec<String>>()
.join(", ");
(
Cow::from(format!(
"|({}, {})| (Some({}), {})",
field.name, enc_names_str, field.name, enc_names_str
)),
Cow::from(format!(
"(None, {})",
enc_fields
.iter()
.map(|enc| enc.default_expr.to_owned())
.collect::<Vec<String>>()
.join(", ")
)),
)
} else {
(Cow::from("Some"), Cow::from("None"))
};
gen_scope
.generate_deserialize(
types,
Expand All @@ -4473,10 +4505,10 @@ fn generate_array_struct_deserialization(
.optional_field(true),
cli,
)
.annotate(&field.name, "", ".map(Some)")
.annotate(&field.name, "", &format!(".map({some_map})"))
.wrap_in_block(type_check_block)
.add_to_code(&mut deser_code);
type_check_else.line("Ok(None)");
type_check_else.line(format!("Ok({defaults})"));
} else {
gen_scope
.generate_deserialize(
Expand Down Expand Up @@ -4535,18 +4567,15 @@ fn generate_array_struct_deserialization(
encoding_vars_output.push(("tag_encoding".to_owned(), "Some(tag_encoding)".to_owned()));
}
for field in record.fields.iter() {
// we don't support deserialization for optional fields so don't even bother
if !field.optional {
for field_enc in encoding_fields(
types,
&field.name,
&field.rust_type.clone().resolve_aliases(),
true,
cli,
) {
encoding_vars_output
.push((field_enc.field_name.clone(), field_enc.field_name.clone()));
}
for field_enc in encoding_fields(
types,
&field.name,
&field.rust_type.clone().resolve_aliases(),
true,
cli,
) {
encoding_vars_output
.push((field_enc.field_name.clone(), field_enc.field_name.clone()));
}
}
}
Expand Down
14 changes: 13 additions & 1 deletion tests/preserve-encodings/input.cddl
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,16 @@ default_uint = uint .default 1337
map_with_defaults = {
? 1 : default_uint
? 2 : text .default "two"
}
}

; TODO: preserve-encodings remembering optional fixed values. Issue: https://github.com/dcSpark/cddl-codegen/issues/205
array_opt_fields = [
; ? x: null,
? a: uint,
? b: text,
c: nint,
? d: text,
y: #6.10(1),
? e: non_overlapping_type_choice_some
; ? z: null,
]
71 changes: 71 additions & 0 deletions tests/preserve-encodings/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -644,4 +644,75 @@ mod tests {
}
}
}

#[test]
fn array_opt_fields() {
let def_encodings = vec![Sz::Inline, Sz::One, Sz::Two, Sz::Four, Sz::Eight];
let str_12_encodings = vec![
StringLenSz::Len(Sz::One),
StringLenSz::Len(Sz::Inline),
StringLenSz::Indefinite(vec![(5, Sz::Two), (7, Sz::One)]),
StringLenSz::Indefinite(vec![(3, Sz::Inline), (0, Sz::Inline), (9, Sz::Four)]),
];
for str_enc in &str_12_encodings {
for def_enc in &def_encodings {
let e_values = [
None,
Some(NonOverlappingTypeChoiceSome::U64 {
uint: 5,
uint_encoding: Some(*def_enc),
}),
Some(NonOverlappingTypeChoiceSome::N64 {
n64: 4,
n64_encoding: Some(*def_enc),
}),
Some(NonOverlappingTypeChoiceSome::Text {
text: "twelve chars".to_owned(),
text_encoding: str_enc.clone().into(),
}),
];
for e in &e_values {
for a in [false, true] {
for b in [false, true] {
for d in [false, true] {
// TODO: preserve-encodings remembering optional fixed values. Issue: https://github.com/dcSpark/cddl-codegen/issues/205
// for x in [false, true] {
// for z in [false, true] {
let mut components: Vec<Vec<u8>> = vec![vec![ARR_INDEF]];
// if x {
// components.push(vec![0xf5]);
// }
if a {
components.push(cbor_int(0, *def_enc));
}
if b {
components.push(cbor_str_sz("hello, world", str_enc.clone()));
}
// c
components.push(cbor_int(-10, *def_enc));
if d {
components.push(cbor_str_sz("cddl-codegen", str_enc.clone()));
}
// y
components.push(cbor_tag_sz(10, *def_enc));
components.push(cbor_int(1, *def_enc));
if let Some(e) = &e {
components.push(e.to_cbor_bytes());
}
// if z {
// //components.push(vec![NULL]);
// }
components.push(vec![BREAK]);
let irregular_bytes = components.into_iter().flatten().clone().collect::<Vec<u8>>();
let irregular = ArrayOptFields::from_cbor_bytes(&irregular_bytes).unwrap();
assert_eq!(irregular_bytes, irregular.to_cbor_bytes());
// }
// }
}
}
}
}
}
}
}
}

0 comments on commit 71f5cce

Please sign in to comment.