···7788(* TLV roundtrip: encode(decode(x)) should produce valid TLV *)
99let test_tlv_decode_encode input =
1010- (* Decoding arbitrary bytes should not crash *)
1110 let decoded = Hap.Tlv.decode input in
1212- (* Re-encoding should produce valid TLV *)
1311 let _ = Hap.Tlv.encode decoded in
1412 check true
1513···2119 let retrieved = Hap.Tlv.get typ decoded in
2220 check_eq ~pp:Format.pp_print_bool (retrieved = Some value) true
23212424-(* Multiple TLV entries roundtrip *)
2222+(* Multiple TLV entries roundtrip - deduplicate types since later adds overwrite *)
2523let test_tlv_multi_roundtrip entries =
2424+ (* Keep only the last value for each type, matching add semantics *)
2525+ let deduped =
2626+ List.fold_left
2727+ (fun acc (typ, value) ->
2828+ List.filter (fun (t, _) -> t <> typ) acc @ [ (typ, value) ])
2929+ [] entries
3030+ in
2631 let tlv =
2732 List.fold_left
2833 (fun acc (typ, value) -> Hap.Tlv.add typ value acc)
2929- Hap.Tlv.empty entries
3434+ Hap.Tlv.empty deduped
3035 in
3136 let encoded = Hap.Tlv.encode tlv in
3237 let decoded = Hap.Tlv.decode encoded in
3333- (* Check that all entries can be retrieved *)
3438 List.iter
3539 (fun (typ, value) ->
3640 let retrieved = Hap.Tlv.get typ decoded in
3741 check_eq ~pp:Format.pp_print_bool (retrieved = Some value) true)
3838- entries
4242+ deduped
39434044(* Category name should never crash *)
4145let test_category_name code =
+4-3
lib/hap.ml
···7171 (List.rev tlv);
7272 Buffer.contents buf
73737474- (* Decode TLV from bytes - concatenate split values *)
7474+ (* Decode TLV from bytes - concatenate split values.
7575+ Stops gracefully on truncated input, returning entries parsed so far. *)
7576 let decode data =
7677 let len = String.length data in
7778 let rec parse offset acc =
7879 if offset >= len then List.rev acc
7979- else if offset + 2 > len then failwith "Invalid TLV: truncated"
8080+ else if offset + 2 > len then List.rev acc
8081 else begin
8182 let typ = Char.code data.[offset] in
8283 let vlen = Char.code data.[offset + 1] in
8383- if offset + 2 + vlen > len then failwith "Invalid TLV: value truncated"
8484+ if offset + 2 + vlen > len then List.rev acc
8485 else begin
8586 let value = String.sub data (offset + 2) vlen in
8687 (* Concatenate with previous if same type *)
+2-1
lib/hap.mli
···206206207207 val decode : string -> t
208208 (** [decode s] deserializes bytes into a TLV container. Consecutive same-type
209209- chunks are concatenated. Raises [Failure] on malformed input. *)
209209+ chunks are concatenated. Truncated input is handled gracefully by
210210+ returning entries parsed so far. *)
210211end
211212212213(** TLV type codes. *)