Skip to content

Commit 6f71032

Browse files
authored
Reusable JSONCoders (#50)
motivation: beter performance changes: * abstract JSONCoders and have a default static instance * make encoding/decoding DRYer across String and Codable
1 parent ac29098 commit 6f71032

File tree

3 files changed

+52
-36
lines changed

3 files changed

+52
-36
lines changed

Sources/AWSLambdaRuntime/Lambda+Codable.swift

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -82,31 +82,51 @@ internal struct CodableVoidLambdaClosureWrapper<In: Decodable>: LambdaHandler {
8282
}
8383
}
8484

85-
/// Implementation of a`ByteBuffer` to `In` and `Out` to `ByteBuffer` codec
86-
/// Using Foundation's JSONEncoder and JSONDecoder
87-
/// Advanced users that want to inject their own codec can do it by overriding these functions.
88-
public extension EventLoopLambdaHandler where In: Decodable, Out: Encodable {
85+
/// Implementation of a`ByteBuffer` to `In` decoding
86+
public extension EventLoopLambdaHandler where In: Decodable {
87+
func decode(buffer: ByteBuffer) throws -> In {
88+
try self.decoder.decode(In.self, from: buffer)
89+
}
90+
}
91+
92+
/// Implementation of `Out` to `ByteBuffer` encoding
93+
public extension EventLoopLambdaHandler where Out: Encodable {
8994
func encode(allocator: ByteBufferAllocator, value: Out) throws -> ByteBuffer? {
9095
// nio will resize the buffer if necessary
91-
// FIXME: reusable JSONEncoder and buffer
9296
var buffer = allocator.buffer(capacity: 1024)
93-
try JSONEncoder().encode(value, into: &buffer)
97+
try self.encoder.encode(value, into: &buffer)
9498
return buffer
9599
}
100+
}
96101

97-
func decode(buffer: ByteBuffer) throws -> In {
98-
// FIXME: reusable JSONDecoder
99-
try JSONDecoder().decode(In.self, from: buffer)
102+
/// Default `ByteBuffer` to `In` decoder using Foundation's JSONDecoder
103+
/// Advanced users that want to inject their own codec can do it by overriding these functions.
104+
public extension EventLoopLambdaHandler where In: Decodable {
105+
var decoder: LambdaCodableDecoder {
106+
Lambda.defaultJSONDecoder
100107
}
101108
}
102109

103-
public extension EventLoopLambdaHandler where In: Decodable, Out == Void {
104-
func encode(allocator: ByteBufferAllocator, value: Void) throws -> ByteBuffer? {
105-
nil
110+
/// Default `Out` to `ByteBuffer` encoder using Foundation's JSONEncoder
111+
/// Advanced users that want to inject their own codec can do it by overriding these functions.
112+
public extension EventLoopLambdaHandler where Out: Encodable {
113+
var encoder: LambdaCodableEncoder {
114+
Lambda.defaultJSONEncoder
106115
}
116+
}
107117

108-
func decode(buffer: ByteBuffer) throws -> In {
109-
// FIXME: reusable JSONDecoder
110-
try JSONDecoder().decode(In.self, from: buffer)
111-
}
118+
public protocol LambdaCodableDecoder {
119+
func decode<T: Decodable>(_ type: T.Type, from buffer: ByteBuffer) throws -> T
120+
}
121+
122+
public protocol LambdaCodableEncoder {
123+
func encode<T: Encodable>(_ value: T, into buffer: inout ByteBuffer) throws
124+
}
125+
126+
private extension Lambda {
127+
static let defaultJSONDecoder = JSONDecoder()
128+
static let defaultJSONEncoder = JSONEncoder()
112129
}
130+
131+
extension JSONDecoder: LambdaCodableDecoder {}
132+
extension JSONEncoder: LambdaCodableEncoder {}

Sources/AWSLambdaRuntime/Lambda+String.swift

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,8 @@ internal struct StringVoidLambdaClosureWrapper: LambdaHandler {
7878
}
7979
}
8080

81-
/// Implementation of a`ByteBuffer` to `String` and `String` to `ByteBuffer` codec
82-
public extension EventLoopLambdaHandler where In == String, Out == String {
83-
func encode(allocator: ByteBufferAllocator, value: String) throws -> ByteBuffer? {
84-
// FIXME: reusable buffer
85-
var buffer = allocator.buffer(capacity: value.utf8.count)
86-
buffer.writeString(value)
87-
return buffer
88-
}
89-
81+
/// Implementation of a`ByteBuffer` to `String` encoding
82+
public extension EventLoopLambdaHandler where In == String {
9083
func decode(buffer: ByteBuffer) throws -> String {
9184
var buffer = buffer
9285
guard let string = buffer.readString(length: buffer.readableBytes) else {
@@ -96,16 +89,12 @@ public extension EventLoopLambdaHandler where In == String, Out == String {
9689
}
9790
}
9891

99-
public extension EventLoopLambdaHandler where In == String, Out == Void {
100-
func encode(allocator: ByteBufferAllocator, value: Void) throws -> ByteBuffer? {
101-
nil
102-
}
103-
104-
func decode(buffer: ByteBuffer) throws -> String {
105-
var buffer = buffer
106-
guard let string = buffer.readString(length: buffer.readableBytes) else {
107-
fatalError("buffer.readString(length: buffer.readableBytes) failed")
108-
}
109-
return string
92+
/// Implementation of `String` to `ByteBuffer` decoding
93+
public extension EventLoopLambdaHandler where Out == String {
94+
func encode(allocator: ByteBufferAllocator, value: String) throws -> ByteBuffer? {
95+
// FIXME: reusable buffer
96+
var buffer = allocator.buffer(capacity: value.utf8.count)
97+
buffer.writeString(value)
98+
return buffer
11099
}
111100
}

Sources/AWSLambdaRuntime/LambdaHandler.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,13 @@ public extension EventLoopLambdaHandler {
107107
}
108108
}
109109

110+
/// Implementation of `ByteBuffer` to `Void` decoding
111+
public extension EventLoopLambdaHandler where Out == Void {
112+
func encode(allocator: ByteBufferAllocator, value: Void) throws -> ByteBuffer? {
113+
nil
114+
}
115+
}
116+
110117
// MARK: - ByteBufferLambdaHandler
111118

112119
/// An `EventLoopFuture` based processing protocol for a Lambda that takes a `ByteBuffer` and returns a `ByteBuffer?` asynchronously.

0 commit comments

Comments
 (0)