use crate::codegen::shared::binding_fields;
use crate::core::ir::TypeDef;
pub(crate) fn needs_decoder_init(ty: &TypeDef) -> bool {
ty.has_default || binding_fields(&ty.fields).any(|field| field.serde_skip_serializing_if)
}
#[cfg(test)]
mod tests {
use super::needs_decoder_init;
use crate::core::ir::{FieldDef, PrimitiveType, TypeDef, TypeRef};
fn vec_field(name: &str, skip_serializing_if: bool) -> FieldDef {
FieldDef {
name: name.to_string(),
ty: TypeRef::Vec(Box::new(TypeRef::Primitive(PrimitiveType::U32))),
serde_skip_serializing_if: skip_serializing_if,
..Default::default()
}
}
fn ty_with(has_default: bool, fields: Vec<FieldDef>) -> TypeDef {
TypeDef {
name: "DocumentNode".to_string(),
has_default,
fields,
..Default::default()
}
}
#[test]
fn a_skippable_field_requires_a_custom_decoder_even_without_a_default_derive() {
assert!(
needs_decoder_init(&ty_with(false, vec![vec_field("children", true)])),
"a `skip_serializing_if` field is absent from the JSON, so the synthesized decoder throws"
);
}
#[test]
fn a_default_deriving_type_still_requires_a_custom_decoder() {
assert!(needs_decoder_init(&ty_with(true, vec![vec_field("children", false)])));
}
#[test]
fn a_type_with_neither_a_default_nor_a_skippable_field_keeps_the_synthesized_decoder() {
assert!(
!needs_decoder_init(&ty_with(false, vec![vec_field("nodes", false)])),
"every key is always written, so Swift's synthesized Codable decodes it correctly"
);
}
#[test]
fn a_binding_excluded_skippable_field_does_not_force_a_decoder() {
let mut excluded = vec_field("children", true);
excluded.binding_excluded = true;
assert!(
!needs_decoder_init(&ty_with(false, vec![excluded])),
"an excluded field is not emitted, so it cannot make the emitted struct undecodable"
);
}
}