From 316f138a470f995a78547e2dad49d6e3b66de1fa Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Thu, 26 Mar 2020 21:04:53 +0100 Subject: [PATCH 1/2] Reuse JSONCoders --- Sources/AWSLambdaRuntime/Lambda+Codable.swift | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Sources/AWSLambdaRuntime/Lambda+Codable.swift b/Sources/AWSLambdaRuntime/Lambda+Codable.swift index b46cac0e..e611a17d 100644 --- a/Sources/AWSLambdaRuntime/Lambda+Codable.swift +++ b/Sources/AWSLambdaRuntime/Lambda+Codable.swift @@ -88,25 +88,30 @@ internal struct CodableVoidLambdaClosureWrapper: LambdaHandler { public extension EventLoopLambdaHandler where In: Decodable, Out: Encodable { func encode(allocator: ByteBufferAllocator, value: Out) throws -> ByteBuffer? { // nio will resize the buffer if necessary - // FIXME: reusable JSONEncoder and buffer var buffer = allocator.buffer(capacity: 1024) - try JSONEncoder().encode(value, into: &buffer) + try Lambda.defaultJSONEncoder.encode(value, into: &buffer) return buffer } func decode(buffer: ByteBuffer) throws -> In { - // FIXME: reusable JSONDecoder - try JSONDecoder().decode(In.self, from: buffer) + try Lambda.defaultJSONDecoder.decode(In.self, from: buffer) } } +private extension Lambda { + /// the default json encoder used in `EventLoopLambdaHandler` if Out == Encodable + static let defaultJSONEncoder = JSONEncoder() + + /// the default json decoder used in `EventLoopLambdaHandler` if In == Decodable + static let defaultJSONDecoder = JSONDecoder() +} + public extension EventLoopLambdaHandler where In: Decodable, Out == Void { func encode(allocator: ByteBufferAllocator, value: Void) throws -> ByteBuffer? { nil } func decode(buffer: ByteBuffer) throws -> In { - // FIXME: reusable JSONDecoder - try JSONDecoder().decode(In.self, from: buffer) + try Lambda.defaultJSONDecoder.decode(In.self, from: buffer) } } From 44e425c584f13b95151a4abfb2b308700f5bc7a7 Mon Sep 17 00:00:00 2001 From: tom doron Date: Thu, 26 Mar 2020 18:42:12 -0700 Subject: [PATCH 2/2] suggestion --- Sources/AWSLambdaRuntime/Lambda+Codable.swift | 53 ++++++++++++------- Sources/AWSLambdaRuntime/Lambda+String.swift | 29 ++++------ Sources/AWSLambdaRuntime/LambdaHandler.swift | 7 +++ 3 files changed, 50 insertions(+), 39 deletions(-) diff --git a/Sources/AWSLambdaRuntime/Lambda+Codable.swift b/Sources/AWSLambdaRuntime/Lambda+Codable.swift index e611a17d..81445c43 100644 --- a/Sources/AWSLambdaRuntime/Lambda+Codable.swift +++ b/Sources/AWSLambdaRuntime/Lambda+Codable.swift @@ -82,36 +82,51 @@ internal struct CodableVoidLambdaClosureWrapper: LambdaHandler { } } -/// Implementation of a`ByteBuffer` to `In` and `Out` to `ByteBuffer` codec -/// Using Foundation's JSONEncoder and JSONDecoder -/// Advanced users that want to inject their own codec can do it by overriding these functions. -public extension EventLoopLambdaHandler where In: Decodable, Out: Encodable { +/// Implementation of a`ByteBuffer` to `In` decoding +public extension EventLoopLambdaHandler where In: Decodable { + func decode(buffer: ByteBuffer) throws -> In { + try self.decoder.decode(In.self, from: buffer) + } +} + +/// Implementation of `Out` to `ByteBuffer` encoding +public extension EventLoopLambdaHandler where Out: Encodable { func encode(allocator: ByteBufferAllocator, value: Out) throws -> ByteBuffer? { // nio will resize the buffer if necessary var buffer = allocator.buffer(capacity: 1024) - try Lambda.defaultJSONEncoder.encode(value, into: &buffer) + try self.encoder.encode(value, into: &buffer) return buffer } +} - func decode(buffer: ByteBuffer) throws -> In { - try Lambda.defaultJSONDecoder.decode(In.self, from: buffer) +/// Default `ByteBuffer` to `In` decoder using Foundation's JSONDecoder +/// Advanced users that want to inject their own codec can do it by overriding these functions. +public extension EventLoopLambdaHandler where In: Decodable { + var decoder: LambdaCodableDecoder { + Lambda.defaultJSONDecoder } } -private extension Lambda { - /// the default json encoder used in `EventLoopLambdaHandler` if Out == Encodable - static let defaultJSONEncoder = JSONEncoder() +/// Default `Out` to `ByteBuffer` encoder using Foundation's JSONEncoder +/// Advanced users that want to inject their own codec can do it by overriding these functions. +public extension EventLoopLambdaHandler where Out: Encodable { + var encoder: LambdaCodableEncoder { + Lambda.defaultJSONEncoder + } +} - /// the default json decoder used in `EventLoopLambdaHandler` if In == Decodable - static let defaultJSONDecoder = JSONDecoder() +public protocol LambdaCodableDecoder { + func decode(_ type: T.Type, from buffer: ByteBuffer) throws -> T } -public extension EventLoopLambdaHandler where In: Decodable, Out == Void { - func encode(allocator: ByteBufferAllocator, value: Void) throws -> ByteBuffer? { - nil - } +public protocol LambdaCodableEncoder { + func encode(_ value: T, into buffer: inout ByteBuffer) throws +} - func decode(buffer: ByteBuffer) throws -> In { - try Lambda.defaultJSONDecoder.decode(In.self, from: buffer) - } +private extension Lambda { + static let defaultJSONDecoder = JSONDecoder() + static let defaultJSONEncoder = JSONEncoder() } + +extension JSONDecoder: LambdaCodableDecoder {} +extension JSONEncoder: LambdaCodableEncoder {} diff --git a/Sources/AWSLambdaRuntime/Lambda+String.swift b/Sources/AWSLambdaRuntime/Lambda+String.swift index f315e0e0..aff8ff19 100644 --- a/Sources/AWSLambdaRuntime/Lambda+String.swift +++ b/Sources/AWSLambdaRuntime/Lambda+String.swift @@ -78,15 +78,8 @@ internal struct StringVoidLambdaClosureWrapper: LambdaHandler { } } -/// Implementation of a`ByteBuffer` to `String` and `String` to `ByteBuffer` codec -public extension EventLoopLambdaHandler where In == String, Out == String { - func encode(allocator: ByteBufferAllocator, value: String) throws -> ByteBuffer? { - // FIXME: reusable buffer - var buffer = allocator.buffer(capacity: value.utf8.count) - buffer.writeString(value) - return buffer - } - +/// Implementation of a`ByteBuffer` to `String` encoding +public extension EventLoopLambdaHandler where In == String { func decode(buffer: ByteBuffer) throws -> String { var buffer = buffer guard let string = buffer.readString(length: buffer.readableBytes) else { @@ -96,16 +89,12 @@ public extension EventLoopLambdaHandler where In == String, Out == String { } } -public extension EventLoopLambdaHandler where In == String, Out == Void { - func encode(allocator: ByteBufferAllocator, value: Void) throws -> ByteBuffer? { - nil - } - - func decode(buffer: ByteBuffer) throws -> String { - var buffer = buffer - guard let string = buffer.readString(length: buffer.readableBytes) else { - fatalError("buffer.readString(length: buffer.readableBytes) failed") - } - return string +/// Implementation of `String` to `ByteBuffer` decoding +public extension EventLoopLambdaHandler where Out == String { + func encode(allocator: ByteBufferAllocator, value: String) throws -> ByteBuffer? { + // FIXME: reusable buffer + var buffer = allocator.buffer(capacity: value.utf8.count) + buffer.writeString(value) + return buffer } } diff --git a/Sources/AWSLambdaRuntime/LambdaHandler.swift b/Sources/AWSLambdaRuntime/LambdaHandler.swift index c47a74df..f9bbcdc6 100644 --- a/Sources/AWSLambdaRuntime/LambdaHandler.swift +++ b/Sources/AWSLambdaRuntime/LambdaHandler.swift @@ -107,6 +107,13 @@ public extension EventLoopLambdaHandler { } } +/// Implementation of `ByteBuffer` to `Void` decoding +public extension EventLoopLambdaHandler where Out == Void { + func encode(allocator: ByteBufferAllocator, value: Void) throws -> ByteBuffer? { + nil + } +} + // MARK: - ByteBufferLambdaHandler /// An `EventLoopFuture` based processing protocol for a Lambda that takes a `ByteBuffer` and returns a `ByteBuffer?` asynchronously.