Skip to content

Commit 6f384ae

Browse files
committed
Add LambdaJSONOutputEncoder
1 parent bf7497a commit 6f384ae

File tree

3 files changed

+130
-3
lines changed

3 files changed

+130
-3
lines changed

Sources/AWSLambdaRuntime/Lambda+Codable.swift

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,37 @@ extension JSONDecoder: LambdaCodableDecoder {}
144144
extension JSONEncoder: LambdaCodableEncoder {}
145145

146146
extension JSONDecoder: AWSLambdaRuntimeCore.LambdaEventDecoder {}
147-
extension JSONEncoder: AWSLambdaRuntimeCore.LambdaOutputEncoder {}
147+
148+
@usableFromInline
149+
package struct LambdaJSONOutputEncoder<Output: Encodable>: LambdaOutputEncoder {
150+
@usableFromInline let jsonEncoder: JSONEncoder
151+
152+
@inlinable
153+
package init(_ jsonEncoder: JSONEncoder) {
154+
self.jsonEncoder = jsonEncoder
155+
}
156+
157+
@inlinable
158+
package func encode(_ value: Output, into buffer: inout ByteBuffer) throws {
159+
try self.jsonEncoder.encode(value, into: &buffer)
160+
}
161+
}
162+
163+
extension LambdaCodableAdapter {
164+
/// Initializes an instance given an encoder, decoder, and a handler with a non-`Void` output.
165+
/// - Parameters:
166+
/// - encoder: The encoder object that will be used to encode the generic ``Output`` obtained from the `handler`'s `outputWriter` into a ``ByteBuffer``.
167+
/// - decoder: The decoder object that will be used to decode the received ``ByteBuffer`` event into the generic ``Event`` type served to the `handler`.
168+
/// - handler: The handler object.
169+
package init(
170+
encoder: JSONEncoder,
171+
decoder: JSONDecoder,
172+
handler: Handler
173+
) where Output: Encodable, Output == Handler.Output, Encoder == LambdaJSONOutputEncoder<Output>, Decoder == JSONDecoder {
174+
self.init(
175+
encoder: LambdaJSONOutputEncoder(encoder),
176+
decoder: decoder,
177+
handler: handler
178+
)
179+
}
180+
}

Sources/AWSLambdaRuntimeCore/NewLambdaContext.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,7 @@ package struct NewLambdaContext: CustomDebugStringConvertible, Sendable {
126126
traceID: String,
127127
invokedFunctionARN: String,
128128
timeout: DispatchTimeInterval,
129-
logger: Logger,
130-
eventLoop: EventLoop
129+
logger: Logger
131130
) -> NewLambdaContext {
132131
NewLambdaContext(
133132
requestID: requestID,
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftAWSLambdaRuntime open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the SwiftAWSLambdaRuntime project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import Testing
16+
import AWSLambdaRuntime
17+
import NIOCore
18+
import Logging
19+
#if canImport(FoundationEssentials)
20+
import FoundationEssentials
21+
#else
22+
import Foundation
23+
#endif
24+
25+
@Suite
26+
struct JSONTests {
27+
28+
let logger = Logger(label: "JSONTests")
29+
30+
struct Foo: Codable {
31+
var bar: String
32+
}
33+
34+
@Test
35+
func testEncodingConformance() {
36+
let encoder = LambdaJSONOutputEncoder<Foo>(JSONEncoder())
37+
let foo = Foo(bar: "baz")
38+
var byteBuffer = ByteBuffer()
39+
40+
#expect(throws: Never.self) {
41+
try encoder.encode(foo, into: &byteBuffer)
42+
}
43+
44+
#expect(byteBuffer == ByteBuffer(string: #"{"bar":"baz"}"#))
45+
}
46+
47+
@Test
48+
func testJSONHandlerWithOutput() async {
49+
let jsonEncoder = JSONEncoder()
50+
let jsonDecoder = JSONDecoder()
51+
52+
let closureHandler = ClosureHandler { (foo: Foo, context) in
53+
foo
54+
}
55+
56+
var handler = LambdaCodableAdapter(encoder: jsonEncoder, decoder: jsonDecoder, handler: LambdaHandlerAdapter(handler: closureHandler))
57+
58+
let event = ByteBuffer(string: #"{"bar":"baz"}"#)
59+
let writer = MockLambdaWriter()
60+
let context = NewLambdaContext.__forTestsOnly(
61+
requestID: UUID().uuidString,
62+
traceID: UUID().uuidString,
63+
invokedFunctionARN: "arn:",
64+
timeout: .milliseconds(6000),
65+
logger: self.logger
66+
)
67+
68+
await #expect(throws: Never.self) {
69+
try await handler.handle(event, responseWriter: writer, context: context)
70+
}
71+
72+
let result = await writer.output
73+
#expect(result == ByteBuffer(string: #"{"bar":"baz"}"#))
74+
}
75+
}
76+
77+
final actor MockLambdaWriter: LambdaResponseStreamWriter {
78+
private var _buffer: ByteBuffer?
79+
80+
var output: ByteBuffer? {
81+
self._buffer
82+
}
83+
84+
func writeAndFinish(_ buffer: ByteBuffer) async throws {
85+
self._buffer = buffer
86+
}
87+
88+
func write(_ buffer: ByteBuffer) async throws {
89+
fatalError("Unexpected call")
90+
}
91+
92+
func finish() async throws {
93+
fatalError("Unexpected call")
94+
}
95+
}

0 commit comments

Comments
 (0)