Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 9 additions & 21 deletions Sources/SmithyCBOR/Deserializer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import struct Foundation.Date
import class Smithy.Schema
import protocol Smithy.SmithyDocument
@_spi(SchemaBasedSerde)
import struct SmithySerialization.DecodedNull
@_spi(SchemaBasedSerde)
import protocol SmithySerialization.DeserializableStruct
@_spi(SchemaBasedSerde)
import typealias SmithySerialization.ReadValueConsumer
import struct SmithySerialization.SerializerError
@_spi(SchemaBasedSerde)
import protocol SmithySerialization.ShapeDeserializer
@_spi(SchemaBasedSerde)
import struct SmithySerialization.UnexpectedNullError

@_spi(SchemaBasedSerde)
public class Deserializer: ShapeDeserializer {
Expand Down Expand Up @@ -202,18 +202,6 @@ public class Deserializer: ShapeDeserializer {
return value
}

public func isNull() throws -> Bool {
try decoder.isNull()
}

public func readNull<T>(_ schema: Schema) throws -> T? {
let next = try decoder.popNext()
guard case .null = next else {
throw CBORDecoderError("member \(schema.id) expected .null but got \(next) instead")
}
return nil
}

public func readStruct<T: DeserializableStruct>(_ schema: Schema, _ value: inout T) throws {
guard depth < maxDepth else { throw CBORDecoderError("Maximum recursive depth exceeded during readStruct()") }
depth += 1
Expand Down Expand Up @@ -250,7 +238,7 @@ public class Deserializer: ShapeDeserializer {
} else {
try skipValue()
}
} catch is UnexpectedNullError {
} catch is DecodedNull {
// skip null
}
guard decoder.hasNext() else {
Expand All @@ -274,7 +262,7 @@ public class Deserializer: ShapeDeserializer {
} else {
try skipValue()
}
} catch is UnexpectedNullError {
} catch is DecodedNull {
// skip null
}
}
Expand Down Expand Up @@ -335,7 +323,7 @@ public class Deserializer: ShapeDeserializer {
do {
let nextElement = try consumer(self)
list.append(nextElement)
} catch is UnexpectedNullError {
} catch is DecodedNull {
// skip the null
}
guard decoder.hasNext() else {
Expand All @@ -349,7 +337,7 @@ public class Deserializer: ShapeDeserializer {
do {
let nextElement = try consumer(self)
list.append(nextElement)
} catch is UnexpectedNullError {
} catch is DecodedNull {
// skip the null
}
}
Expand Down Expand Up @@ -382,7 +370,7 @@ public class Deserializer: ShapeDeserializer {
do {
let value = try consumer(self)
map[key] = value
} catch is UnexpectedNullError {
} catch is DecodedNull {
// skip the null
}
guard decoder.hasNext() else {
Expand All @@ -399,7 +387,7 @@ public class Deserializer: ShapeDeserializer {
do {
let value = try consumer(self)
map[key] = value
} catch is UnexpectedNullError {
} catch is DecodedNull {
// skip the null
}
}
Expand All @@ -415,7 +403,7 @@ public class Deserializer: ShapeDeserializer {
private func nullCheck() throws {
if try decoder.isNull() {
_ = try decoder.popNext()
throw UnexpectedNullError()
throw DecodedNull()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,6 @@ struct EventContentDeserializer: ShapeDeserializer {
throw notImplemented
}

func readNull<T>(_ schema: Schema) throws -> T? {
throw notImplemented
}

func isNull() throws -> Bool {
throw notImplemented
}

var containerSize: Int { -1 }

private var notImplemented: SerializerError { .init("Not implemented") }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,6 @@ struct EventHeaderDeserializer: ShapeDeserializer {
return value
}

func readNull<T>(_ schema: Schema) throws -> T? {
throw notImplemented
}

func isNull() throws -> Bool {
throw notImplemented
}

var containerSize: Int { -1 }

private var notImplemented: SerializerError { .init("Not implemented") }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,6 @@ public struct EventStreamDeserializer: ShapeDeserializer {
throw notImplemented
}

public func readNull<T>(_ schema: Schema) throws -> T? {
throw notImplemented
}

public func isNull() throws -> Bool {
throw notImplemented
}

public var containerSize: Int { -1 }

private var notImplemented: SerializerError { .init("Not implemented") }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,6 @@ struct EventUnionDeserializer: ShapeDeserializer {
throw notImplemented
}

func readNull<T>(_ schema: Schema) throws -> T? {
throw notImplemented
}

func isNull() throws -> Bool {
throw notImplemented
}

var containerSize: Int { -1 }

private var notImplemented: SerializerError { .init("Not implemented") }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,6 @@ struct SDKUnknownDeserializer: ShapeDeserializer {
throw notImplemented
}

func readNull<T>(_ schema: Schema) throws -> T? {
throw notImplemented
}

func isNull() throws -> Bool {
throw notImplemented
}

var containerSize: Int { -1 }

private var notImplemented: SerializerError { .init("Not implemented") }
Expand Down
18 changes: 5 additions & 13 deletions Sources/SmithyJSON/Deserializer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import class Foundation.NSNumber
@_spi(SchemaBasedSerde)
@_spi(SmithyDocumentImpl) import Smithy
@_spi(SchemaBasedSerde)
import struct SmithySerialization.DecodedNull
@_spi(SchemaBasedSerde)
import protocol SmithySerialization.DeserializableStruct
import struct SmithySerialization.SerializerError
@_spi(SchemaBasedSerde)
import protocol SmithySerialization.ShapeDeserializer
import struct SmithySerialization.UnexpectedNullError
@_spi(SmithyTimestamps) import struct SmithyTimestamps.TimestampFormatter

@_spi(SchemaBasedSerde)
Expand Down Expand Up @@ -81,7 +82,7 @@ public final class Deserializer: ShapeDeserializer {
return try list.compactMap {
do {
return try consumer(Deserializer(usesJSONNameTrait: usesJSONNameTrait, node: $0))
} catch is UnexpectedNullError {
} catch is DecodedNull {
// JSON deserializer "tolerates" nulls in non-sparse lists.
// This nil will be compacted out of the returned list.
return nil
Expand All @@ -95,7 +96,7 @@ public final class Deserializer: ShapeDeserializer {
return try map.compactMapValues {
do {
return try consumer(Deserializer(usesJSONNameTrait: usesJSONNameTrait, node: $0))
} catch is UnexpectedNullError {
} catch is DecodedNull {
// JSON deserializer "tolerates" nulls in non-sparse maps.
// This nil will be compacted out of the returned map.
return nil
Expand Down Expand Up @@ -247,15 +248,6 @@ public final class Deserializer: ShapeDeserializer {
return date
}

public func readNull<T>(_ schema: Schema) throws -> T? {
// no action required
return nil
}

public func isNull() throws -> Bool {
value == .null
}

public var containerSize: Int {
switch value {
case .object(let object):
Expand All @@ -281,7 +273,7 @@ public final class Deserializer: ShapeDeserializer {

private func nullCheck() throws {
if case .null = self.value {
throw UnexpectedNullError()
throw DecodedNull()
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions Sources/SmithySerialization/DecodedNull.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

/// An error indicating that a null was encountered when deserializing a value.
///
/// This error may be handled if null is expected, or thrown back to the caller
/// if not.
@_spi(SchemaBasedSerde)
public struct DecodedNull: Error {

public init() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import enum Smithy.ByteStream
import class Smithy.Schema
import protocol Smithy.SmithyDocument

/// The protocol for a shape deserializer, which converts encoded data into modeled types.
///
/// If `null` is encountered while reading to any supported type, the `DecodedNull` error should be thrown back to the caller.
/// `DecodedNull` may be caught and handled when a null value is to be expected or (at least) tolerated.
@_spi(SchemaBasedSerde)
public protocol ShapeDeserializer {
func readStruct<T: DeserializableStruct>(_ schema: Schema, _ value: inout T) throws
Expand All @@ -30,12 +34,10 @@ public protocol ShapeDeserializer {
func readString(_ schema: Schema) throws -> String
func readDocument(_ schema: Schema) throws -> any SmithyDocument
func readTimestamp(_ schema: Schema) throws -> Date
func readNull<T>(_ schema: Schema) throws -> T?
func readDataStream(_ schema: Schema) throws -> ByteStream
func readEventStream<E: DeserializableStruct & Sendable>(
_ schema: Schema
) throws -> AsyncThrowingStream<E, any Error>
func isNull() throws -> Bool
var containerSize: Int { get }
}

Expand All @@ -54,20 +56,20 @@ public extension ShapeDeserializer {

func readSparseList<E>(_ schema: Schema, _ consumer: ReadValueConsumer<E>) throws -> [E?] {
try readList(schema) { deserializer in
if try deserializer.isNull() {
return try deserializer.readNull(schema.resolveTarget.member)
} else {
do {
return try consumer(deserializer)
} catch is DecodedNull {
return nil
}
}
}

func readSparseMap<V>(_ schema: Schema, _ consumer: ReadValueConsumer<V>) throws -> [String: V?] {
try readMap(schema) { deserializer in
if try deserializer.isNull() {
return try deserializer.readNull(schema.resolveTarget.value)
} else {
do {
return try consumer(deserializer)
} catch is DecodedNull {
return nil
}
}
}
Expand Down
13 changes: 0 additions & 13 deletions Sources/SmithySerialization/UnexpectedNullError.swift

This file was deleted.

1 change: 1 addition & 0 deletions test-sdks/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ let package = Package(
.product(name: "Smithy", package: "smithy-swift"),
.product(name: "AwsCommonRuntimeKit", package: "aws-crt-swift"),
testSDKProduct("MaxRecursion"),
testSDKProduct("NullTolerance"),
]
),
.testTarget(
Expand Down
Loading
Loading