Skip to content

Reusable JSONCoders #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 27, 2020
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
52 changes: 36 additions & 16 deletions Sources/AWSLambdaRuntime/Lambda+Codable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,31 +82,51 @@ internal struct CodableVoidLambdaClosureWrapper<In: Decodable>: 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
// FIXME: reusable JSONEncoder and buffer
var buffer = allocator.buffer(capacity: 1024)
try JSONEncoder().encode(value, into: &buffer)
try self.encoder.encode(value, into: &buffer)
return buffer
}
}

func decode(buffer: ByteBuffer) throws -> In {
// FIXME: reusable JSONDecoder
try JSONDecoder().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
}
}

public extension EventLoopLambdaHandler where In: Decodable, Out == Void {
func encode(allocator: ByteBufferAllocator, value: Void) throws -> ByteBuffer? {
nil
/// 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
}
}

func decode(buffer: ByteBuffer) throws -> In {
// FIXME: reusable JSONDecoder
try JSONDecoder().decode(In.self, from: buffer)
}
public protocol LambdaCodableDecoder {
func decode<T: Decodable>(_ type: T.Type, from buffer: ByteBuffer) throws -> T
}

public protocol LambdaCodableEncoder {
func encode<T: Encodable>(_ value: T, into buffer: inout ByteBuffer) throws
}

private extension Lambda {
static let defaultJSONDecoder = JSONDecoder()
static let defaultJSONEncoder = JSONEncoder()
}

extension JSONDecoder: LambdaCodableDecoder {}
extension JSONEncoder: LambdaCodableEncoder {}
29 changes: 9 additions & 20 deletions Sources/AWSLambdaRuntime/Lambda+String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}
}
7 changes: 7 additions & 0 deletions Sources/AWSLambdaRuntime/LambdaHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down