@@ -18,20 +18,112 @@ import NIOCore
1818// MARK: - SimpleLambdaHandler
1919
2020/// Strongly typed, processing protocol for a Lambda that takes a user defined
21- /// ``LambdaHandler /Event`` and returns a user defined
22- /// ``LambdaHandler /Output`` asynchronously.
21+ /// ``SimpleLambdaHandler /Event`` and returns a user defined
22+ /// ``SimpleLambdaHandler /Output`` asynchronously.
2323///
2424/// - note: Most users should implement the ``LambdaHandler`` protocol instead
2525/// which defines the Lambda initialization method.
26- @available ( macOS 12 , iOS 15 , tvOS 15 , watchOS 8 , * )
27- public protocol SimpleLambdaHandler : LambdaHandler {
26+ public protocol SimpleLambdaHandler {
27+ /// The lambda function's input. In most cases this should be `Codable`. If your event originates from an
28+ /// AWS service, have a look at [AWSLambdaEvents](https://github.com/swift-server/swift-aws-lambda-events),
29+ /// which provides a number of commonly used AWS Event implementations.
30+ associatedtype Event
31+ /// The lambda function's output. Can be `Void`.
32+ associatedtype Output
33+
2834 init ( )
35+
36+ /// The Lambda handling method.
37+ /// Concrete Lambda handlers implement this method to provide the Lambda functionality.
38+ ///
39+ /// - parameters:
40+ /// - event: Event of type `Event` representing the event or request.
41+ /// - context: Runtime ``LambdaContext``.
42+ ///
43+ /// - Returns: A Lambda result ot type `Output`.
44+ func handle( _ event: Event , context: LambdaContext ) async throws -> Output
45+
46+ /// Encode a response of type ``Output`` to `ByteBuffer`.
47+ /// Concrete Lambda handlers implement this method to provide coding functionality.
48+ /// - parameters:
49+ /// - value: Response of type ``Output``.
50+ /// - buffer: A `ByteBuffer` to encode into, will be overwritten.
51+ ///
52+ /// - Returns: A `ByteBuffer` with the encoded version of the `value`.
53+ func encode( value: Output , into buffer: inout ByteBuffer ) throws
54+
55+ /// Decode a `ByteBuffer` to a request or event of type ``Event``.
56+ /// Concrete Lambda handlers implement this method to provide coding functionality.
57+ ///
58+ /// - parameters:
59+ /// - buffer: The `ByteBuffer` to decode.
60+ ///
61+ /// - Returns: A request or event of type ``Event``.
62+ func decode( buffer: ByteBuffer ) throws -> Event
63+ }
64+
65+ final class CodableSimpleLambdaHandler < Underlying: SimpleLambdaHandler > : ByteBufferLambdaHandler {
66+ private let handler : Underlying
67+ private var outputBuffer : ByteBuffer
68+
69+ @inlinable
70+ static func makeHandler( context: LambdaInitializationContext ) -> EventLoopFuture < CodableSimpleLambdaHandler > {
71+ let promise = context. eventLoop. makePromise ( of: CodableSimpleLambdaHandler< Underlying> . self )
72+ promise. completeWithTask {
73+ let handler = Underlying ( )
74+ return CodableSimpleLambdaHandler ( handler: handler, allocator: context. allocator)
75+ }
76+ return promise. futureResult
77+ }
78+
79+ @inlinable
80+ init ( handler: Underlying , allocator: ByteBufferAllocator ) {
81+ self . handler = handler
82+ self . outputBuffer = allocator. buffer ( capacity: 1024 * 1024 )
83+ }
84+
85+ @inlinable
86+ func handle( _ buffer: ByteBuffer , context: LambdaContext ) -> EventLoopFuture < ByteBuffer ? > {
87+ let promise = context. eventLoop. makePromise ( of: ByteBuffer ? . self)
88+ promise. completeWithTask {
89+ let input : Underlying . Event
90+ do {
91+ input = try self . handler. decode ( buffer: buffer)
92+ } catch {
93+ throw CodecError . requestDecoding ( error)
94+ }
95+
96+ let output = try await self . handler. handle ( input, context: context)
97+
98+ do {
99+ self . outputBuffer. clear ( )
100+ try self . handler. encode ( value: output, into: & self . outputBuffer)
101+ return self . outputBuffer
102+ } catch {
103+ throw CodecError . responseEncoding ( error)
104+ }
105+ }
106+ return promise. futureResult
107+ }
108+ }
109+
110+ /// Implementation of `ByteBuffer` to `Void` decoding.
111+ extension SimpleLambdaHandler where Output == Void {
112+ @inlinable
113+ public func encode( value: Output , into buffer: inout ByteBuffer ) throws { }
29114}
30115
31- @available ( macOS 12 , iOS 15 , tvOS 15 , watchOS 8 , * )
32116extension SimpleLambdaHandler {
33- public init ( context: LambdaInitializationContext ) async throws {
34- self . init ( )
117+ /// Initializes and runs the Lambda function.
118+ ///
119+ /// If you precede your ``SimpleLambdaHandler`` conformer's declaration with the
120+ /// [@main](https://docs.swift.org/swift-book/ReferenceManual/Attributes.html#ID626)
121+ /// attribute, the system calls the conformer's `main()` method to launch the lambda function.
122+ ///
123+ /// The lambda runtime provides a default implementation of the method that manages the launch
124+ /// process.
125+ public static func main( ) {
126+ _ = Lambda . run ( configuration: . init( ) , handlerType: Self . self)
35127 }
36128}
37129
@@ -44,7 +136,6 @@ extension SimpleLambdaHandler {
44136/// - note: Most users should implement this protocol instead of the lower
45137/// level protocols ``EventLoopLambdaHandler`` and
46138/// ``ByteBufferLambdaHandler``.
47- @available ( macOS 12 , iOS 15 , tvOS 15 , watchOS 8 , * )
48139public protocol LambdaHandler {
49140 /// The lambda function's input. In most cases this should be `Codable`. If your event originates from an
50141 /// AWS service, have a look at [AWSLambdaEvents](https://github.com/swift-server/swift-aws-lambda-events),
@@ -90,7 +181,6 @@ public protocol LambdaHandler {
90181 func decode( buffer: ByteBuffer ) throws -> Event
91182}
92183
93- @available ( macOS 12 , iOS 15 , tvOS 15 , watchOS 8 , * )
94184final class CodableLambdaHandler < Underlying: LambdaHandler > : ByteBufferLambdaHandler {
95185 private let handler : Underlying
96186 private var outputBuffer : ByteBuffer
@@ -137,17 +227,15 @@ final class CodableLambdaHandler<Underlying: LambdaHandler>: ByteBufferLambdaHan
137227}
138228
139229/// Implementation of `ByteBuffer` to `Void` decoding.
140- @available ( macOS 12 , iOS 15 , tvOS 15 , watchOS 8 , * )
141230extension LambdaHandler where Output == Void {
142231 @inlinable
143232 public func encode( value: Output , into buffer: inout ByteBuffer ) throws { }
144233}
145234
146- @available ( macOS 12 , iOS 15 , tvOS 15 , watchOS 8 , * )
147235extension LambdaHandler {
148236 /// Initializes and runs the Lambda function.
149237 ///
150- /// If you precede your ``ByteBufferLambdaHandler `` conformer's declaration with the
238+ /// If you precede your ``LambdaHandler `` conformer's declaration with the
151239 /// [@main](https://docs.swift.org/swift-book/ReferenceManual/Attributes.html#ID626)
152240 /// attribute, the system calls the conformer's `main()` method to launch the lambda function.
153241 ///
@@ -161,7 +249,6 @@ extension LambdaHandler {
161249/// unchecked sendable wrapper for the handler
162250/// this is safe since lambda runtime is designed to calls the handler serially
163251@usableFromInline
164- @available ( macOS 12 , iOS 15 , tvOS 15 , watchOS 8 , * )
165252internal struct UncheckedSendableHandler < Underlying: LambdaHandler , Event, Output> : @unchecked Sendable where Event == Underlying . Event , Output == Underlying . Output {
166253 @usableFromInline
167254 let underlying : Underlying
@@ -283,7 +370,7 @@ internal final class CodableEventLoopLambdaHandler<Underlying: EventLoopLambdaHa
283370extension EventLoopLambdaHandler {
284371 /// Initializes and runs the Lambda function.
285372 ///
286- /// If you precede your ``ByteBufferLambdaHandler `` conformer's declaration with the
373+ /// If you precede your ``EventLoopLambdaHandler `` conformer's declaration with the
287374 /// [@main](https://docs.swift.org/swift-book/ReferenceManual/Attributes.html#ID626)
288375 /// attribute, the system calls the conformer's `main()` method to launch the lambda function.
289376 ///
0 commit comments