use super::super::swift::generate_swift_for_tests;
fn struct_bodies(swift: &str) -> Vec<(String, String)> {
let mut bodies = Vec::new();
for chunk in swift.split("\npublic struct ").skip(1) {
let Some(name) = chunk.split([':', ' ', '\n']).next() else {
continue;
};
let body = chunk.split("\n}\n").next().unwrap_or(chunk);
bodies.push((name.to_string(), body.to_string()));
}
bodies
}
#[test]
fn every_struct_with_a_custom_encoder_carries_the_custom_decoder() {
let swift = generate_swift_for_tests();
let bodies = struct_bodies(&swift);
assert!(
!bodies.is_empty(),
"no structs were parsed out of the Swift artifact, so this asserts nothing"
);
let mut paired = 0usize;
for (name, body) in &bodies {
if !body.contains("public func encode(to encoder: Encoder) throws") {
continue;
}
assert!(
body.contains("public init(from decoder: Decoder) throws"),
"{name} emits a custom encoder but no custom decoder, so a key it \
always writes is read back with `decodeIfPresent` and an omitted \
key decodes as nil instead of being refused"
);
paired += 1;
}
assert!(
paired > 0,
"no struct emits a custom encoder, so the pairing above was never tested"
);
}
#[test]
fn the_compaction_struct_refuses_an_omitted_required_nullable_key() {
let swift = generate_swift_for_tests();
let bodies = struct_bodies(&swift);
let body = |wanted: &str| {
bodies
.iter()
.find(|(name, _)| name == wanted)
.map(|(_, body)| body.clone())
.unwrap_or_else(|| panic!("{wanted} is missing from the Swift artifact"))
};
let compacted = body("HarnACPTranscriptCompactedUpdateMetaHarn");
assert!(
compacted.contains("snapshotAssetId = try values.decode(String?.self, forKey: .snapshotAssetId)"),
"the compaction struct must read its required-nullable key unconditionally, got:\n{compacted}"
);
let log = body("HarnACPLogUpdateMetaHarn");
assert!(
log.contains("values.contains(.fields)"),
"the log struct must still distinguish an absent JSON field from a null one, got:\n{log}"
);
}