mirror of
https://github.com/swift-server/swift-aws-lambda-events.git
synced 2026-05-03 07:42:27 +00:00
Fixes and tests for decoding binary items and empty lists in DynamoDBEvent.Decoder (#103)
Cleaned up version of [#61](https://github.com/awslabs/swift-aws-lambda-events/pull/61) that also has tests. This PR makes it so that in lists, the decoder will not try to access the 0th index of an empty array. This PR will also make it so that `AttributeValue`s of type `.binary` will properly decode to base64 Strings when String is put as the type in the the `Decodable`. To avoid including `Data` in the code, I included code from the original source of the base 64 decoding methods (https://github.com/fabianfett/swift-base64-kit) to add in the corresponding encoding methods. However, I saw lots of Foundation is imported throughout so I reverted it. What are your thoughts on this matter? I also added tests that aim to make these failure points more resilient in the future.
This commit is contained in:
@@ -462,11 +462,14 @@ extension DynamoDBEvent {
|
||||
func decode(_ type: String.Type, forKey key: K) throws -> String {
|
||||
let value = try getValue(forKey: key)
|
||||
|
||||
guard case .string(let string) = value else {
|
||||
switch value {
|
||||
case .string(let string):
|
||||
return string
|
||||
case .binary(let binary):
|
||||
return Data(binary).base64EncodedString()
|
||||
default:
|
||||
throw self.createTypeMismatchError(type: type, forKey: key, value: value)
|
||||
}
|
||||
|
||||
return string
|
||||
}
|
||||
|
||||
func decode(_ type: Double.Type, forKey key: K) throws -> Double {
|
||||
@@ -651,11 +654,14 @@ extension DynamoDBEvent {
|
||||
}
|
||||
|
||||
func decode(_: String.Type) throws -> String {
|
||||
guard case .string(let string) = self.value else {
|
||||
switch self.value {
|
||||
case .string(let string):
|
||||
return string
|
||||
case .binary(let binary):
|
||||
return Data(binary).base64EncodedString()
|
||||
default:
|
||||
throw self.createTypeMismatchError(type: String.self, value: self.value)
|
||||
}
|
||||
|
||||
return string
|
||||
}
|
||||
|
||||
func decode(_: Double.Type) throws -> Double {
|
||||
@@ -769,6 +775,9 @@ extension DynamoDBEvent {
|
||||
self.codingPath = codingPath
|
||||
self.array = array
|
||||
self.count = array.count
|
||||
|
||||
// No need to decode if array is empty
|
||||
self.isAtEnd = array.isEmpty
|
||||
}
|
||||
|
||||
mutating func decodeNil() throws -> Bool {
|
||||
|
||||
@@ -251,4 +251,59 @@ struct DynamoDBTests {
|
||||
#expect(test?.foo == "bar")
|
||||
#expect(test?.xyz == 123)
|
||||
}
|
||||
|
||||
@Test func decoderEmptyList() {
|
||||
let value: [String: DynamoDBEvent.AttributeValue] = [
|
||||
"fooList": .list([])
|
||||
]
|
||||
|
||||
struct Test: Codable {
|
||||
let fooList: [Int]
|
||||
}
|
||||
|
||||
let test = try? DynamoDBEvent.Decoder().decode(Test.self, from: value)
|
||||
#expect(test?.fooList == [])
|
||||
}
|
||||
|
||||
@Test func decoderNonEmptyList() {
|
||||
let value: [String: DynamoDBEvent.AttributeValue] = [
|
||||
"fooList": .list([.string("test")])
|
||||
]
|
||||
|
||||
struct Test: Codable {
|
||||
let fooList: [String]
|
||||
}
|
||||
|
||||
let test = try? DynamoDBEvent.Decoder().decode(Test.self, from: value)
|
||||
#expect(test?.fooList == ["test"])
|
||||
}
|
||||
|
||||
@Test func decoderBinaryToBase64KeyedDecodingContainer() {
|
||||
let value: [String: DynamoDBEvent.AttributeValue] = [
|
||||
"xyz": .binary([0x74, 0x65, 0x73, 0x74]) // UTF8 for "test"
|
||||
]
|
||||
|
||||
struct Test: Codable {
|
||||
let xyz: String
|
||||
}
|
||||
|
||||
let test = try? DynamoDBEvent.Decoder().decode(Test.self, from: value)
|
||||
#expect(test?.xyz == "dGVzdA==") // base64 for "test"
|
||||
}
|
||||
|
||||
@Test func decoderBinaryToBase64SingleValueDecodingContainer() {
|
||||
let value: DynamoDBEvent.AttributeValue = .binary([0x74, 0x65, 0x73, 0x74]) // UTF8 for "test"
|
||||
|
||||
let test = try? DynamoDBEvent.Decoder().decode(String.self, from: value)
|
||||
#expect(test == "dGVzdA==") // base64 for "test"
|
||||
}
|
||||
|
||||
@Test func decoderBinaryToBase64UnkeyedDecodingContainer() {
|
||||
let value: DynamoDBEvent.AttributeValue = .list([
|
||||
.binary([0x74, 0x65, 0x73, 0x74]) // UTF8 for "test"
|
||||
])
|
||||
|
||||
let test = try? DynamoDBEvent.Decoder().decode([String].self, from: value)
|
||||
#expect(test == ["dGVzdA=="]) // base64 for "test"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user