13
13
//===----------------------------------------------------------------------===//
14
14
15
15
import Foundation // for JSON
16
+ import NIO
17
+ import NIOFoundationCompat
16
18
17
19
/// Extension to the `Lambda` companion to enable execution of Lambdas that take and return `Codable` payloads.
18
20
/// This is the most common way to use this library in AWS Lambda, since its JSON based.
@@ -32,21 +34,18 @@ extension Lambda {
32
34
}
33
35
34
36
// for testing
35
- internal static func run< In: Decodable , Out: Encodable > ( configuration: Configuration = . init( ) , closure: @escaping LambdaCodableClosure < In , Out > ) -> LambdaLifecycleResult {
37
+ internal static func run< In: Decodable , Out: Encodable > ( configuration: Configuration = . init( ) , closure: @escaping LambdaCodableClosure < In , Out > ) -> Result < Int , Error > {
36
38
return self . run ( handler: LambdaClosureWrapper ( closure) , configuration: configuration)
37
39
}
38
40
39
41
// for testing
40
- internal static func run< Handler> ( handler: Handler , configuration: Configuration = . init( ) ) -> LambdaLifecycleResult where Handler: LambdaCodableHandler {
42
+ internal static func run< Handler> ( handler: Handler , configuration: Configuration = . init( ) ) -> Result < Int , Error > where Handler: LambdaCodableHandler {
41
43
return self . run ( handler: handler as LambdaHandler , configuration: configuration)
42
44
}
43
45
}
44
46
45
- /// A result type for a Lambda that returns a generic `Out`, having `Out` extend `Encodable`.
46
- public typealias LambdaCodableResult < Out> = Result < Out , Error >
47
-
48
- /// A callback for a Lambda that returns a `LambdaCodableResult<Out>` result type, having `Out` extend `Encodable`.
49
- public typealias LambdaCodableCallback < Out> = ( LambdaCodableResult < Out > ) -> Void
47
+ /// A callback for a Lambda that returns a `Result<Out, Error>` result type, having `Out` extend `Encodable`.
48
+ public typealias LambdaCodableCallback < Out> = ( Result < Out , Error > ) -> Void
50
49
51
50
/// A processing closure for a Lambda that takes an `In` and returns an `Out` via `LambdaCodableCallback<Out>` asynchronously,
52
51
/// having `In` and `Out` extending `Decodable` and `Encodable` respectively.
@@ -73,27 +72,27 @@ public extension LambdaCodableHandler {
73
72
/// LambdaCodableCodec is an abstract/empty implementation for codec which does `Encodable` -> `[UInt8]` encoding and `[UInt8]` -> `Decodable' decoding.
74
73
// TODO: would be nicer to use a protocol instead of this "abstract class", but generics get in the way
75
74
public class LambdaCodableCodec < In: Decodable , Out: Encodable > {
76
- func encode( _: Out ) -> Result < [ UInt8 ] , Error > { fatalError ( " not implmented " ) }
77
- func decode( _: [ UInt8 ] ) -> Result < In , Error > { fatalError ( " not implmented " ) }
75
+ func encode( _: Out ) -> Result < ByteBuffer , Error > { fatalError ( " not implmented " ) }
76
+ func decode( _: ByteBuffer ) -> Result < In , Error > { fatalError ( " not implmented " ) }
78
77
}
79
78
80
79
/// Default implementation of `Encodable` -> `[UInt8]` encoding and `[UInt8]` -> `Decodable' decoding
81
80
public extension LambdaCodableHandler {
82
- func handle( context: LambdaContext , payload: [ UInt8 ] , callback : @escaping ( LambdaResult ) -> Void ) {
81
+ func handle( context: LambdaContext , payload: ByteBuffer , promise : EventLoopPromise < ByteBuffer > ) {
83
82
switch self . codec. decode ( payload) {
84
83
case . failure( let error) :
85
- return callback ( . failure ( Errors . requestDecoding ( error) ) )
84
+ return promise . fail ( Errors . requestDecoding ( error) )
86
85
case . success( let payloadAsCodable) :
87
86
self . handle ( context: context, payload: payloadAsCodable) { result in
88
87
switch result {
89
88
case . failure( let error) :
90
- return callback ( . failure ( error) )
89
+ return promise . fail ( error)
91
90
case . success( let encodable) :
92
91
switch self . codec. encode ( encodable) {
93
92
case . failure( let error) :
94
- return callback ( . failure ( Errors . responseEncoding ( error) ) )
95
- case . success( let codableAsBytes ) :
96
- return callback ( . success ( codableAsBytes ) )
93
+ return promise . fail ( Errors . responseEncoding ( error) )
94
+ case . success( let buffer ) :
95
+ return promise . succeed ( buffer )
97
96
}
98
97
}
99
98
}
@@ -107,18 +106,25 @@ public extension LambdaCodableHandler {
107
106
private final class LambdaCodableJsonCodec < In: Decodable , Out: Encodable > : LambdaCodableCodec < In , Out > {
108
107
private let encoder = JSONEncoder ( )
109
108
private let decoder = JSONDecoder ( )
109
+ private let allocator = ByteBufferAllocator ( )
110
110
111
- public override func encode( _ value: Out ) -> Result < [ UInt8 ] , Error > {
111
+ public override func encode( _ value: Out ) -> Result < ByteBuffer , Error > {
112
112
do {
113
- return . success( try [ UInt8] ( self . encoder. encode ( value) ) )
113
+ let data = try self . encoder. encode ( value)
114
+ var buffer = self . allocator. buffer ( capacity: data. count)
115
+ buffer. writeBytes ( data)
116
+ return . success( buffer)
114
117
} catch {
115
118
return . failure( error)
116
119
}
117
120
}
118
121
119
- public override func decode( _ data : [ UInt8 ] ) -> Result < In , Error > {
122
+ public override func decode( _ buffer : ByteBuffer ) -> Result < In , Error > {
120
123
do {
121
- return . success( try self . decoder. decode ( In . self, from: Data ( data) ) )
124
+ guard let data = buffer. getData ( at: buffer. readerIndex, length: buffer. readableBytes) else {
125
+ throw Errors . invalidBuffer
126
+ }
127
+ return . success( try self . decoder. decode ( In . self, from: data) )
122
128
} catch {
123
129
return . failure( error)
124
130
}
@@ -141,4 +147,5 @@ private struct LambdaClosureWrapper<In: Decodable, Out: Encodable>: LambdaCodabl
141
147
private enum Errors : Error {
142
148
case responseEncoding( Error )
143
149
case requestDecoding( Error )
150
+ case invalidBuffer
144
151
}
0 commit comments