Union parity: the unknown-arm-list case carries its Pending id; rust and ts keep unit-arm codec tests on a separate union

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-14 19:46:22 +02:00
commit bd27f7a34b
3 changed files with 17 additions and 4 deletions

View file

@ -95,6 +95,13 @@ enum Outcome {
Ceiling(IdArm),
}
// The codec's unit arm (no members, written [key, []]), kept apart from the golden: a document list's arms carry ids.
#[derive(Clone, Debug, PartialEq, CultUnion)]
enum UnitOutcome {
#[cultcache(key = 2)]
Denied,
}
#[derive(Clone, Debug, PartialEq, CultSlots)]
struct PendingArm {
#[cultcache(key = 0)]
@ -241,6 +248,12 @@ fn union_surface_decodes_and_reencodes() {
assert_eq!(rmp_serde::to_vec(&value).unwrap(), payload);
}
#[test]
fn a_unit_arm_is_a_key_and_an_empty_slots_array() {
assert_eq!(rmp_serde::to_vec(&UnitOutcome::Denied).unwrap(), [0x92, 0x02, 0x90]);
assert_eq!(rmp_serde::from_slice::<UnitOutcome>(&[0x92, 0x02, 0x90]).unwrap(), UnitOutcome::Denied);
}
#[test]
fn an_id_only_arm_is_a_key_and_a_one_slot_array() {
let mut bytes = vec![0x92, 0x02, 0x91, 0xac];
@ -307,8 +320,8 @@ fn a_union_that_is_not_a_key_and_slots_pair_is_refused_naming_the_enum() {
("a unit arm with slots", rmp_serde::to_vec(&(2u64, ("CANARY-slot",))).unwrap()),
];
for (label, bytes) in cases {
let message = rmp_serde::from_slice::<Outcome>(&bytes).unwrap_err().to_string();
assert!(message.contains("Outcome"), "{label}: {message}");
let message = rmp_serde::from_slice::<UnitOutcome>(&bytes).unwrap_err().to_string();
assert!(message.contains("UnitOutcome"), "{label}: {message}");
assert!(!message.contains("CANARY"), "{label}: {message}");
}
}

View file

@ -64,7 +64,7 @@ interface Surface {
id: string;
version: number;
root: Node | null;
outcomes: (Outcome | null)[];
outcomes: (GoldenOutcome | null)[];
part: Item | null;
crafted: CraftedItem | null;
missing: Node | null;

View file

@ -282,7 +282,7 @@ namespace GameCult.Caching.Tests
new Case("unknown-arm-field.msgpack", "refused", "Node", 3, "unknown-arm",
Surface(root: ArmOf(3, Str("r"), Str(Canary)))),
new Case("unknown-arm-list.msgpack", "refused", "Outcome", 7, "unknown-arm",
Surface(outcomes: Slots(ArmOf(0, Str("wait")), ArmOf(7, Str(Canary))))),
Surface(outcomes: Slots(ArmOf(0, Str("wait"), Str("0000000000a1")), ArmOf(7, Str(Canary))))),
new Case("unknown-arm-nested.msgpack", "refused", "Node", 9, "unknown-arm",
Surface(root: BoxArm("0000000000c0", Slots(BoxArm("0000000000d3", Slots(BoxArm("0000000000d4", Slots(ArmOf(9, Str("deep"), Str(Canary)))))))))),
new Case("inner-union-outer-key.msgpack", "refused", "CraftedItem", 2, "unknown-arm",