From 99af692232cc0b1420bc1599b7916af703efe3da Mon Sep 17 00:00:00 2001 From: deadcafe Date: Wed, 14 Oct 2026 19:47:16 +0530 Subject: [PATCH] Allow encoding empty bare inner lists Motivation: Encoding an empty array as a list member or dictionary value threw invalidTypeForItem. Those values start out as itemOrInnerList and only become an inner list once something is appended, so an empty array left the node undecided and inserting it into the parent failed. Modifications: Resolve itemOrInnerList to an empty inner list as soon as an unkeyed container is requested, since only an inner list can be encoded that way. Add an encoder test covering empty inner lists in lists and dictionaries. Result: Empty bare inner lists encode as "()". --- .../Encoder/StructuredFieldValueEncoder.swift | 6 +++++- .../StructuredFieldEncoderTests.swift | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Sources/StructuredFieldValues/Encoder/StructuredFieldValueEncoder.swift b/Sources/StructuredFieldValues/Encoder/StructuredFieldValueEncoder.swift index ac8530f..f5aeabc 100644 --- a/Sources/StructuredFieldValues/Encoder/StructuredFieldValueEncoder.swift +++ b/Sources/StructuredFieldValues/Encoder/StructuredFieldValueEncoder.swift @@ -209,7 +209,11 @@ extension _StructuredFieldEncoder: Encoder { } func unkeyedContainer() -> UnkeyedEncodingContainer { - StructuredFieldUnkeyedEncodingContainer(encoder: self) + if case .itemOrInnerList(let params) = self.currentStackEntry.storage { + // This is an inner list, even if nothing is ever appended to it. + self.currentStackEntry.storage = .innerList(InnerList(bareInnerList: [], parameters: params)) + } + return StructuredFieldUnkeyedEncodingContainer(encoder: self) } func singleValueContainer() -> SingleValueEncodingContainer { diff --git a/Tests/StructuredFieldValuesTests/StructuredFieldEncoderTests.swift b/Tests/StructuredFieldValuesTests/StructuredFieldEncoderTests.swift index a6ce1b8..4e17ce3 100644 --- a/Tests/StructuredFieldValuesTests/StructuredFieldEncoderTests.swift +++ b/Tests/StructuredFieldValuesTests/StructuredFieldEncoderTests.swift @@ -310,6 +310,17 @@ final class StructuredFieldEncoderTests: XCTestCase { XCTAssertEqual(Array("(1 2 3), (4 5 6)".utf8), try encoder.encode(List(header))) } + func testEmptyInnerListsBare() throws { + struct DictionaryField: StructuredFieldValue { + static let structuredFieldType: StructuredFieldType = .dictionary + var x: [Int] + } + + let encoder = StructuredFieldValueEncoder() + XCTAssertEqual(Array("(), (1 2 3), ()".utf8), try encoder.encode(List([[], [1, 2, 3], []]))) + XCTAssertEqual(Array("x=()".utf8), try encoder.encode(DictionaryField(x: []))) + } + func testListFieldInnerListsParameters() throws { struct Integers: Equatable, Codable { var items: [Int]