From 6489caa6fa1e508ca596605da2aac38171450c31 Mon Sep 17 00:00:00 2001 From: Josh Elkins Date: Wed, 22 Oct 2025 10:52:34 -0500 Subject: [PATCH 1/8] fix: Throw error on invalid JSON in response --- .../Reader/Reader+JSONDeserialization.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift b/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift index 42c660101..f04700a39 100644 --- a/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift +++ b/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift @@ -6,19 +6,19 @@ // import struct Foundation.Data -import class Foundation.NSError import class Foundation.JSONSerialization -import class Foundation.NSNull extension Reader { public static func from(data: Data) throws -> Reader { + // Empty bodies are allowed. When the body is empty, + // return a reader with no JSON content. guard !data.isEmpty else { return Reader(nodeInfo: "", parent: nil) } - do { - let jsonObject = try JSONSerialization.jsonObject(with: data, options: [.fragmentsAllowed]) - return try Reader(nodeInfo: "", jsonObject: jsonObject) - } catch let error as NSError where error.domain == "NSCocoaErrorDomain" && error.code == 3840 { - return try Reader(nodeInfo: "", jsonObject: [:]) - } + + // Attempt to parse JSON from the non-empty body. + // Throw an error if JSON is invalid. + // (Determine whether to wrap this error) + let jsonObject = try JSONSerialization.jsonObject(with: data) + return try Reader(nodeInfo: "", jsonObject: jsonObject) } } From 7c431b8eeea1b8b5e63b24d4965781fe4264da88 Mon Sep 17 00:00:00 2001 From: Josh Elkins Date: Wed, 22 Oct 2025 11:18:39 -0500 Subject: [PATCH 2/8] Fix ClientRuntime tests that use JSON fragments --- .../OrchestratorTests/OrchestratorTests.swift | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Tests/ClientRuntimeTests/OrchestratorTests/OrchestratorTests.swift b/Tests/ClientRuntimeTests/OrchestratorTests/OrchestratorTests.swift index 8cb8135df..55c463568 100644 --- a/Tests/ClientRuntimeTests/OrchestratorTests/OrchestratorTests.swift +++ b/Tests/ClientRuntimeTests/OrchestratorTests/OrchestratorTests.swift @@ -223,10 +223,11 @@ class OrchestratorTests: XCTestCase { .attributes(attributes) .serialize({ input, builder, _ in trace.append("serialize") + let data = try JSONEncoder().encode(["foo": input.foo]) builder.withMethod(.get) .withPath("/") .withHost("localhost") - .withBody(.data(try! JSONEncoder().encode(input.foo))) + .withBody(.data(data)) }) .deserialize({ response, _ in trace.append("deserialize") @@ -234,8 +235,8 @@ class OrchestratorTests: XCTestCase { guard case let .data(data) = response.body else { return TestOutput(bar: "") } - let bar = try! JSONDecoder().decode(String.self, from: data!) - return TestOutput(bar: bar) + let object = try! JSONDecoder().decode([String: String].self, from: data!) + return TestOutput(bar: object["foo"]!) } else { let responseReader = try SmithyJSON.Reader.from(data: try await response.data()) let baseError = try TestBaseError(httpResponse: response, responseReader: responseReader, noErrorWrapping: true) @@ -1373,7 +1374,8 @@ class OrchestratorTests: XCTestCase { let orchestrator = traceOrchestrator(trace: trace) .retryStrategy(DefaultRetryStrategy(options: RetryStrategyOptions(backoffStrategy: ImmediateBackoffStrategy()))) .serialize({ (input: TestInput, builder: HTTPRequestBuilder, context) in - builder.withBody(.data(Data("\"\(input.foo)\"".utf8))) + let data = try JSONEncoder().encode(["foo": input.foo]) + builder.withBody(.data(data)) }) .executeRequest(executeRequest) let result = await asyncResult { From da8cbd1f48a9532a343473ecd9a5c2573ea6cdda Mon Sep 17 00:00:00 2001 From: Josh Elkins Date: Thu, 6 Nov 2025 15:36:00 -0600 Subject: [PATCH 3/8] Add InvalidEncodingError to project --- Package.swift | 13 +++++++++++-- .../Reader/Reader+JSONDeserialization.swift | 10 ++++++++-- Sources/SmithySerde/InvalidEncodingError.swift | 15 +++++++++++++++ Sources/SmithyXML/Reader/Reader+libxml2.swift | 6 +++++- Tests/SmithyJSONTests/ReaderTests.swift | 17 ++++++++++++++--- 5 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 Sources/SmithySerde/InvalidEncodingError.swift diff --git a/Package.swift b/Package.swift index a781bbcb8..fb0cff47e 100644 --- a/Package.swift +++ b/Package.swift @@ -30,6 +30,7 @@ let package = Package( ], products: [ .library(name: "Smithy", targets: ["Smithy"]), + .library(name: "SmithySerde", targets: ["SmithySerde"]), .library(name: "ClientRuntime", targets: ["ClientRuntime"]), .library(name: "SmithyRetriesAPI", targets: ["SmithyRetriesAPI"]), .library(name: "SmithyRetries", targets: ["SmithyRetries"]), @@ -74,6 +75,12 @@ let package = Package( .product(name: "Logging", package: "swift-log"), ] ), + .target( + name: "SmithySerde", + dependencies: [ + "Smithy", + ] + ), .target( name: "ClientRuntime", dependencies: [ @@ -137,6 +144,7 @@ let package = Package( .target( name: "SmithyXML", dependencies: [ + "SmithySerde", "SmithyReadWrite", "SmithyTimestamps", libXML2DependencyOrNil @@ -145,6 +153,7 @@ let package = Package( .target( name: "SmithyJSON", dependencies: [ + "SmithySerde", "SmithyReadWrite", "SmithyTimestamps" ] @@ -284,7 +293,7 @@ let package = Package( ), .testTarget( name: "SmithyXMLTests", - dependencies: ["SmithyXML", "ClientRuntime"] + dependencies: ["SmithySerde", "SmithyXML", "ClientRuntime"] ), .testTarget( name: "SmithyHTTPAuthTests", @@ -296,7 +305,7 @@ let package = Package( ), .testTarget( name: "SmithyJSONTests", - dependencies: ["SmithyJSON", "ClientRuntime", "SmithyTestUtil"] + dependencies: ["SmithySerde", "SmithyJSON", "ClientRuntime", "SmithyTestUtil"] ), .testTarget( name: "SmithyFormURLTests", diff --git a/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift b/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift index f04700a39..d517522d1 100644 --- a/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift +++ b/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift @@ -7,18 +7,24 @@ import struct Foundation.Data import class Foundation.JSONSerialization +import struct SmithySerde.InvalidEncodingError extension Reader { public static func from(data: Data) throws -> Reader { // Empty bodies are allowed. When the body is empty, // return a reader with no JSON content. - guard !data.isEmpty else { return Reader(nodeInfo: "", parent: nil) } + guard !data.isEmpty else { return try Reader(nodeInfo: "", jsonObject: [:]) } // Attempt to parse JSON from the non-empty body. // Throw an error if JSON is invalid. // (Determine whether to wrap this error) - let jsonObject = try JSONSerialization.jsonObject(with: data) + let jsonObject: Any + do { + jsonObject = try JSONSerialization.jsonObject(with: data) + } catch { + throw InvalidEncodingError(wrapped: error) + } return try Reader(nodeInfo: "", jsonObject: jsonObject) } } diff --git a/Sources/SmithySerde/InvalidEncodingError.swift b/Sources/SmithySerde/InvalidEncodingError.swift new file mode 100644 index 000000000..4edfc9ee8 --- /dev/null +++ b/Sources/SmithySerde/InvalidEncodingError.swift @@ -0,0 +1,15 @@ +// +// Copyright Amazon.com Inc. or its affiliates. +// All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + +public struct InvalidEncodingError: Error { + public var localizedDescription: String { "The data in the response could not be parsed" } + public let wrapped: Error // this will be the underlying error thrown by the parser implementation + + public init(wrapped: Error) { + self.wrapped = wrapped + } +} diff --git a/Sources/SmithyXML/Reader/Reader+libxml2.swift b/Sources/SmithyXML/Reader/Reader+libxml2.swift index f8c8f110d..8fed260ad 100644 --- a/Sources/SmithyXML/Reader/Reader+libxml2.swift +++ b/Sources/SmithyXML/Reader/Reader+libxml2.swift @@ -7,6 +7,7 @@ @preconcurrency import libxml2 import struct Foundation.Data +import struct SmithySerde.InvalidEncodingError extension Reader { @@ -21,7 +22,9 @@ extension Reader { guard let buffer else { return Reader() } // Read the buffer into a XML document tree - guard let doc = xmlReadMemory(buffer.pointee.content, Int32(count), "", "UTF-8", 0) else { return Reader() } + guard let doc = xmlReadMemory(buffer.pointee.content, Int32(count), "", "UTF-8", 0) else { + throw InvalidEncodingError(wrapped: XMLError.parsingError) + } // Get rootNode ptr. Just a ptr to inside the doc struct, so no memory allocated guard let rootNode = xmlDocGetRootElement(doc) else { return Reader() } @@ -154,4 +157,5 @@ private struct XMLError: Error { static let memoryError = XMLError("XML buffer could not be allocated") static let invalidNode = XMLError("XML node was invalid") static let invalidNodeName = XMLError("XML node name was invalid") + static let parsingError = XMLError("The XML could not be parsed") } diff --git a/Tests/SmithyJSONTests/ReaderTests.swift b/Tests/SmithyJSONTests/ReaderTests.swift index 76a10b30f..797ad7a51 100644 --- a/Tests/SmithyJSONTests/ReaderTests.swift +++ b/Tests/SmithyJSONTests/ReaderTests.swift @@ -6,14 +6,16 @@ // import XCTest +import struct SmithySerde.InvalidEncodingError @testable @_spi(SmithyReadWrite) import SmithyJSON -class ReaderTests: XCTestCase { +final class ReaderTests: XCTestCase { - func test_readsNil() async throws { + func test_readsEmptyDataAsEmptyJSONObject() async throws { let jsonData = Data() let reader = try SmithyJSON.Reader.from(data: jsonData) - XCTAssertEqual(reader.jsonNode, nil) + XCTAssertEqual(reader.jsonNode, .object) + XCTAssert(reader.children.isEmpty) } func test_readsAJSONObject() async throws { @@ -24,4 +26,13 @@ class ReaderTests: XCTestCase { XCTAssertEqual(reader.children.count, 1) XCTAssertEqual(try reader["property"].readIfPresent(), "potato") } + + func test_throwsOnInvalidJSON() async throws { + let jsonData = Data(""" + { "json": "incomplet + """.utf8) + XCTAssertThrowsError(try SmithyJSON.Reader.from(data: jsonData)) { error in + XCTAssert(error is InvalidEncodingError) + } + } } From b085e73d86f0b40ca9ecce7c044c6c058a6d6c4e Mon Sep 17 00:00:00 2001 From: Josh Elkins Date: Tue, 11 Nov 2025 15:38:49 -0600 Subject: [PATCH 4/8] Fix RestJSON protocol tests --- .../SmithyJSON/Reader/Reader+JSONDeserialization.swift | 8 +++----- Tests/SmithyJSONTests/ReaderTests.swift | 5 ++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift b/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift index ff4e4aa2c..74dd81638 100644 --- a/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift +++ b/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift @@ -16,17 +16,15 @@ extension Reader { public static func from(data: Data) throws -> Reader { // Empty bodies are allowed. When the body is empty, // return a reader with no JSON content. - guard !data.isEmpty else { return try Reader(nodeInfo: "", jsonObject: [:]) } + guard !data.isEmpty else { return Reader(nodeInfo: "", parent: nil) } // Attempt to parse JSON from the non-empty body. // Throw an error if JSON is invalid. - // (Determine whether to wrap this error) - let jsonObject: Any do { - jsonObject = try JSONSerialization.jsonObject(with: data) + let jsonObject = try JSONSerialization.jsonObject(with: data) + return try Reader(nodeInfo: "", jsonObject: jsonObject) } catch { throw InvalidEncodingError(wrapped: error) } - return try Reader(nodeInfo: "", jsonObject: jsonObject) } } diff --git a/Tests/SmithyJSONTests/ReaderTests.swift b/Tests/SmithyJSONTests/ReaderTests.swift index 797ad7a51..591b7f2bd 100644 --- a/Tests/SmithyJSONTests/ReaderTests.swift +++ b/Tests/SmithyJSONTests/ReaderTests.swift @@ -11,11 +11,10 @@ import struct SmithySerde.InvalidEncodingError final class ReaderTests: XCTestCase { - func test_readsEmptyDataAsEmptyJSONObject() async throws { + func test_readsEmptyDataAsNil() async throws { let jsonData = Data() let reader = try SmithyJSON.Reader.from(data: jsonData) - XCTAssertEqual(reader.jsonNode, .object) - XCTAssert(reader.children.isEmpty) + XCTAssertNil(reader.jsonNode) } func test_readsAJSONObject() async throws { From e09e9f5e7abd0a9d2070c2b4b8f5c3fae4c63775 Mon Sep 17 00:00:00 2001 From: Josh Elkins Date: Mon, 24 Nov 2025 11:43:10 -0500 Subject: [PATCH 5/8] Rename module to SmithySerialization --- Package.swift | 12 ++++++------ .../Reader/Reader+JSONDeserialization.swift | 2 +- .../InvalidEncodingError.swift | 0 Sources/SmithyXML/Reader/Reader+libxml2.swift | 2 +- Tests/SmithyJSONTests/ReaderTests.swift | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) rename Sources/{SmithySerde => SmithySerialization}/InvalidEncodingError.swift (100%) diff --git a/Package.swift b/Package.swift index 1bae2d369..7ff13a43b 100644 --- a/Package.swift +++ b/Package.swift @@ -30,7 +30,7 @@ let package = Package( ], products: [ .library(name: "Smithy", targets: ["Smithy"]), - .library(name: "SmithySerde", targets: ["SmithySerde"]), + .library(name: "SmithySerialization", targets: ["SmithySerialization"]), .library(name: "ClientRuntime", targets: ["ClientRuntime"]), .library(name: "SmithyRetriesAPI", targets: ["SmithyRetriesAPI"]), .library(name: "SmithyRetries", targets: ["SmithyRetries"]), @@ -76,7 +76,7 @@ let package = Package( ] ), .target( - name: "SmithySerde", + name: "SmithySerialization", dependencies: [ "Smithy", ] @@ -144,7 +144,7 @@ let package = Package( .target( name: "SmithyXML", dependencies: [ - "SmithySerde", + "SmithySerialization", "SmithyReadWrite", "SmithyTimestamps", libXML2DependencyOrNil @@ -153,7 +153,7 @@ let package = Package( .target( name: "SmithyJSON", dependencies: [ - "SmithySerde", + "SmithySerialization", "SmithyReadWrite", "SmithyTimestamps" ] @@ -293,7 +293,7 @@ let package = Package( ), .testTarget( name: "SmithyXMLTests", - dependencies: ["SmithySerde", "SmithyXML", "ClientRuntime"] + dependencies: ["SmithySerialization", "SmithyXML", "ClientRuntime"] ), .testTarget( name: "SmithyHTTPAuthTests", @@ -305,7 +305,7 @@ let package = Package( ), .testTarget( name: "SmithyJSONTests", - dependencies: ["SmithySerde", "SmithyJSON", "ClientRuntime", "SmithyTestUtil"] + dependencies: ["SmithySerialization", "SmithyJSON", "ClientRuntime", "SmithyTestUtil"] ), .testTarget( name: "SmithyFormURLTests", diff --git a/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift b/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift index 74dd81638..6d0898f2b 100644 --- a/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift +++ b/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift @@ -9,7 +9,7 @@ import struct Foundation.Data import class Foundation.JSONSerialization import class Foundation.NSError import class Foundation.NSNull -import struct SmithySerde.InvalidEncodingError +import struct SmithySerialization.InvalidEncodingError extension Reader { diff --git a/Sources/SmithySerde/InvalidEncodingError.swift b/Sources/SmithySerialization/InvalidEncodingError.swift similarity index 100% rename from Sources/SmithySerde/InvalidEncodingError.swift rename to Sources/SmithySerialization/InvalidEncodingError.swift diff --git a/Sources/SmithyXML/Reader/Reader+libxml2.swift b/Sources/SmithyXML/Reader/Reader+libxml2.swift index 1913cacd3..63aba72ec 100644 --- a/Sources/SmithyXML/Reader/Reader+libxml2.swift +++ b/Sources/SmithyXML/Reader/Reader+libxml2.swift @@ -7,7 +7,7 @@ import struct Foundation.Data @preconcurrency import libxml2 -import struct SmithySerde.InvalidEncodingError +import struct SmithySerialization.InvalidEncodingError extension Reader { diff --git a/Tests/SmithyJSONTests/ReaderTests.swift b/Tests/SmithyJSONTests/ReaderTests.swift index 591b7f2bd..9bf09e4b1 100644 --- a/Tests/SmithyJSONTests/ReaderTests.swift +++ b/Tests/SmithyJSONTests/ReaderTests.swift @@ -6,7 +6,7 @@ // import XCTest -import struct SmithySerde.InvalidEncodingError +import struct SmithySerialization.InvalidEncodingError @testable @_spi(SmithyReadWrite) import SmithyJSON final class ReaderTests: XCTestCase { From 98e660dcc2fc5c5687aa84f9d3924eeb3001953c Mon Sep 17 00:00:00 2001 From: Josh Elkins Date: Mon, 24 Nov 2025 12:16:31 -0500 Subject: [PATCH 6/8] Refactor & document InvalidEncodingError --- .../InvalidEncodingError.swift | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Sources/SmithySerialization/InvalidEncodingError.swift b/Sources/SmithySerialization/InvalidEncodingError.swift index 4edfc9ee8..b0b777761 100644 --- a/Sources/SmithySerialization/InvalidEncodingError.swift +++ b/Sources/SmithySerialization/InvalidEncodingError.swift @@ -5,11 +5,24 @@ // SPDX-License-Identifier: Apache-2.0 // -public struct InvalidEncodingError: Error { - public var localizedDescription: String { "The data in the response could not be parsed" } - public let wrapped: Error // this will be the underlying error thrown by the parser implementation +/// The data being deserialized was invalid, and a response could not be parsed. +/// +/// If an error of this type is received, it indicates a bug either on the server or client. Please file a [bug ticket](https://github.com/smithy-lang/smithy-swift/issues). +public struct InvalidEncodingError { - public init(wrapped: Error) { + /// The error thrown by the deserializing implementation. + /// + /// The exact error returned may vary depending on the encoding in use. + public let wrapped: any Swift.Error // this will be the underlying error thrown by the parser implementation + + public init(wrapped: any Error) { self.wrapped = wrapped } } + +extension InvalidEncodingError: Error { + + public var localizedDescription: String { + "The data in the response could not be parsed. More info: \(wrapped)" + } +} From 13bcf00e8adae8faa2ed2d8e2a87a7b6970ca4bc Mon Sep 17 00:00:00 2001 From: Josh Elkins Date: Mon, 24 Nov 2025 12:37:44 -0500 Subject: [PATCH 7/8] Add XML test, rename error --- .../Reader/Reader+JSONDeserialization.swift | 4 ++-- .../InvalidEncodingError.swift | 4 ++-- Sources/SmithyXML/Reader/Reader+libxml2.swift | 4 ++-- Tests/SmithyJSONTests/ReaderTests.swift | 4 ++-- Tests/SmithyXMLTests/ReaderTests.swift | 16 ++++++++++++++++ 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift b/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift index 6d0898f2b..5efb0bb95 100644 --- a/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift +++ b/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift @@ -9,7 +9,7 @@ import struct Foundation.Data import class Foundation.JSONSerialization import class Foundation.NSError import class Foundation.NSNull -import struct SmithySerialization.InvalidEncodingError +import struct SmithySerialization.ResponseEncodingError extension Reader { @@ -24,7 +24,7 @@ extension Reader { let jsonObject = try JSONSerialization.jsonObject(with: data) return try Reader(nodeInfo: "", jsonObject: jsonObject) } catch { - throw InvalidEncodingError(wrapped: error) + throw ResponseEncodingError(wrapped: error) } } } diff --git a/Sources/SmithySerialization/InvalidEncodingError.swift b/Sources/SmithySerialization/InvalidEncodingError.swift index b0b777761..4e9bd8894 100644 --- a/Sources/SmithySerialization/InvalidEncodingError.swift +++ b/Sources/SmithySerialization/InvalidEncodingError.swift @@ -8,7 +8,7 @@ /// The data being deserialized was invalid, and a response could not be parsed. /// /// If an error of this type is received, it indicates a bug either on the server or client. Please file a [bug ticket](https://github.com/smithy-lang/smithy-swift/issues). -public struct InvalidEncodingError { +public struct ResponseEncodingError { /// The error thrown by the deserializing implementation. /// @@ -20,7 +20,7 @@ public struct InvalidEncodingError { } } -extension InvalidEncodingError: Error { +extension ResponseEncodingError: Error { public var localizedDescription: String { "The data in the response could not be parsed. More info: \(wrapped)" diff --git a/Sources/SmithyXML/Reader/Reader+libxml2.swift b/Sources/SmithyXML/Reader/Reader+libxml2.swift index 63aba72ec..e3fb81c4e 100644 --- a/Sources/SmithyXML/Reader/Reader+libxml2.swift +++ b/Sources/SmithyXML/Reader/Reader+libxml2.swift @@ -7,7 +7,7 @@ import struct Foundation.Data @preconcurrency import libxml2 -import struct SmithySerialization.InvalidEncodingError +import struct SmithySerialization.ResponseEncodingError extension Reader { @@ -23,7 +23,7 @@ extension Reader { // Read the buffer into a XML document tree guard let doc = xmlReadMemory(buffer.pointee.content, Int32(count), "", "UTF-8", 0) else { - throw InvalidEncodingError(wrapped: XMLError.parsingError) + throw ResponseEncodingError(wrapped: XMLError.parsingError) } // Get rootNode ptr. Just a ptr to inside the doc struct, so no memory allocated diff --git a/Tests/SmithyJSONTests/ReaderTests.swift b/Tests/SmithyJSONTests/ReaderTests.swift index 9bf09e4b1..98d08dbf4 100644 --- a/Tests/SmithyJSONTests/ReaderTests.swift +++ b/Tests/SmithyJSONTests/ReaderTests.swift @@ -6,7 +6,7 @@ // import XCTest -import struct SmithySerialization.InvalidEncodingError +import struct SmithySerialization.ResponseEncodingError @testable @_spi(SmithyReadWrite) import SmithyJSON final class ReaderTests: XCTestCase { @@ -31,7 +31,7 @@ final class ReaderTests: XCTestCase { { "json": "incomplet """.utf8) XCTAssertThrowsError(try SmithyJSON.Reader.from(data: jsonData)) { error in - XCTAssert(error is InvalidEncodingError) + XCTAssert(error is ResponseEncodingError) } } } diff --git a/Tests/SmithyXMLTests/ReaderTests.swift b/Tests/SmithyXMLTests/ReaderTests.swift index 34af35b8d..627807e51 100644 --- a/Tests/SmithyXMLTests/ReaderTests.swift +++ b/Tests/SmithyXMLTests/ReaderTests.swift @@ -7,6 +7,7 @@ import XCTest @testable @_spi(SmithyReadWrite) import SmithyXML +import struct SmithySerialization.ResponseEncodingError class ReaderTests: XCTestCase { let xmlData = Data(""" @@ -59,4 +60,19 @@ class ReaderTests: XCTestCase { XCTAssertEqual(reader.children[1].nodeInfo.namespaceDef, .init(prefix: "a2abc", uri: "https://def.ghi.com")) XCTAssertEqual(reader.children.count, 3) } + + func test_invalidXML_throws() throws { + // Same data as above, but the last closing tag is missing its '<' + let invalidXML = Data(""" + + x + y + z +/a> +""".utf8) + + XCTAssertThrowsError(try Reader.from(data: invalidXML)) { error in + XCTAssert(error is ResponseEncodingError) + } + } } From 216cda623e797af9d70e00d8e573b8c8c9f4bc09 Mon Sep 17 00:00:00 2001 From: Josh Elkins Date: Tue, 25 Nov 2025 10:10:47 -0500 Subject: [PATCH 8/8] Change error name to ResponseDecodingError --- Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift | 4 ++-- ...InvalidEncodingError.swift => ResponseDecodingError.swift} | 4 ++-- Sources/SmithyXML/Reader/Reader+libxml2.swift | 4 ++-- Tests/SmithyJSONTests/ReaderTests.swift | 4 ++-- Tests/SmithyXMLTests/ReaderTests.swift | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) rename Sources/SmithySerialization/{InvalidEncodingError.swift => ResponseDecodingError.swift} (91%) diff --git a/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift b/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift index 5efb0bb95..022a79254 100644 --- a/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift +++ b/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift @@ -9,7 +9,7 @@ import struct Foundation.Data import class Foundation.JSONSerialization import class Foundation.NSError import class Foundation.NSNull -import struct SmithySerialization.ResponseEncodingError +import struct SmithySerialization.ResponseDecodingError extension Reader { @@ -24,7 +24,7 @@ extension Reader { let jsonObject = try JSONSerialization.jsonObject(with: data) return try Reader(nodeInfo: "", jsonObject: jsonObject) } catch { - throw ResponseEncodingError(wrapped: error) + throw ResponseDecodingError(wrapped: error) } } } diff --git a/Sources/SmithySerialization/InvalidEncodingError.swift b/Sources/SmithySerialization/ResponseDecodingError.swift similarity index 91% rename from Sources/SmithySerialization/InvalidEncodingError.swift rename to Sources/SmithySerialization/ResponseDecodingError.swift index 4e9bd8894..9b3bafb17 100644 --- a/Sources/SmithySerialization/InvalidEncodingError.swift +++ b/Sources/SmithySerialization/ResponseDecodingError.swift @@ -8,7 +8,7 @@ /// The data being deserialized was invalid, and a response could not be parsed. /// /// If an error of this type is received, it indicates a bug either on the server or client. Please file a [bug ticket](https://github.com/smithy-lang/smithy-swift/issues). -public struct ResponseEncodingError { +public struct ResponseDecodingError { /// The error thrown by the deserializing implementation. /// @@ -20,7 +20,7 @@ public struct ResponseEncodingError { } } -extension ResponseEncodingError: Error { +extension ResponseDecodingError: Error { public var localizedDescription: String { "The data in the response could not be parsed. More info: \(wrapped)" diff --git a/Sources/SmithyXML/Reader/Reader+libxml2.swift b/Sources/SmithyXML/Reader/Reader+libxml2.swift index e3fb81c4e..bd85eac9f 100644 --- a/Sources/SmithyXML/Reader/Reader+libxml2.swift +++ b/Sources/SmithyXML/Reader/Reader+libxml2.swift @@ -7,7 +7,7 @@ import struct Foundation.Data @preconcurrency import libxml2 -import struct SmithySerialization.ResponseEncodingError +import struct SmithySerialization.ResponseDecodingError extension Reader { @@ -23,7 +23,7 @@ extension Reader { // Read the buffer into a XML document tree guard let doc = xmlReadMemory(buffer.pointee.content, Int32(count), "", "UTF-8", 0) else { - throw ResponseEncodingError(wrapped: XMLError.parsingError) + throw ResponseDecodingError(wrapped: XMLError.parsingError) } // Get rootNode ptr. Just a ptr to inside the doc struct, so no memory allocated diff --git a/Tests/SmithyJSONTests/ReaderTests.swift b/Tests/SmithyJSONTests/ReaderTests.swift index 98d08dbf4..fd256e84b 100644 --- a/Tests/SmithyJSONTests/ReaderTests.swift +++ b/Tests/SmithyJSONTests/ReaderTests.swift @@ -6,7 +6,7 @@ // import XCTest -import struct SmithySerialization.ResponseEncodingError +import struct SmithySerialization.ResponseDecodingError @testable @_spi(SmithyReadWrite) import SmithyJSON final class ReaderTests: XCTestCase { @@ -31,7 +31,7 @@ final class ReaderTests: XCTestCase { { "json": "incomplet """.utf8) XCTAssertThrowsError(try SmithyJSON.Reader.from(data: jsonData)) { error in - XCTAssert(error is ResponseEncodingError) + XCTAssert(error is ResponseDecodingError) } } } diff --git a/Tests/SmithyXMLTests/ReaderTests.swift b/Tests/SmithyXMLTests/ReaderTests.swift index 627807e51..b2767cba5 100644 --- a/Tests/SmithyXMLTests/ReaderTests.swift +++ b/Tests/SmithyXMLTests/ReaderTests.swift @@ -7,7 +7,7 @@ import XCTest @testable @_spi(SmithyReadWrite) import SmithyXML -import struct SmithySerialization.ResponseEncodingError +import struct SmithySerialization.ResponseDecodingError class ReaderTests: XCTestCase { let xmlData = Data(""" @@ -72,7 +72,7 @@ class ReaderTests: XCTestCase { """.utf8) XCTAssertThrowsError(try Reader.from(data: invalidXML)) { error in - XCTAssert(error is ResponseEncodingError) + XCTAssert(error is ResponseDecodingError) } } }