Skip to content

Commit 6cebe1a

Browse files
committed
Merge branch 'main' into sebsto/docker
2 parents 7d26fe7 + 6d886aa commit 6cebe1a

File tree

12 files changed

+358
-108
lines changed

12 files changed

+358
-108
lines changed

.github/workflows/pull_request.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ jobs:
1111
with:
1212
license_header_check_project_name: "SwiftAWSLambdaRuntime"
1313
shell_check_enabled: false
14-
api_breakage_check_container_image: "swiftlang/swift:nightly-6.0-jammy"
15-
docs_check_container_image: "swiftlang/swift:nightly-6.0-jammy"
14+
api_breakage_check_container_image: "swift:6.0-noble"
15+
docs_check_container_image: "swift:6.0-noble"
1616

1717
unit-tests:
1818
name: Unit tests

Package.swift

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,16 @@ let package = Package(
2323
.library(name: "AWSLambdaTesting", targets: ["AWSLambdaTesting"]),
2424
],
2525
dependencies: [
26-
.package(url: "https://github.com/apple/swift-nio.git", .upToNextMajor(from: "2.72.0")),
27-
.package(url: "https://github.com/apple/swift-log.git", .upToNextMajor(from: "1.5.4")),
28-
.package(url: "https://github.com/apple/swift-testing.git", branch: "swift-DEVELOPMENT-SNAPSHOT-2024-08-29-a"),
26+
.package(url: "https://github.com/apple/swift-nio.git", from: "2.72.0"),
27+
.package(url: "https://github.com/apple/swift-log.git", from: "1.5.4"),
2928
],
3029
targets: [
3130
.target(
3231
name: "AWSLambdaRuntime",
3332
dependencies: [
3433
.byName(name: "AWSLambdaRuntimeCore"),
3534
.product(name: "NIOCore", package: "swift-nio"),
36-
.product(name: "NIOFoundationCompat", package: "swift-nio"),
3735
],
38-
swiftSettings: [.swiftLanguageMode(.v5)]
3936
),
4037
.target(
4138
name: "AWSLambdaRuntimeCore",
@@ -70,7 +67,6 @@ let package = Package(
7067
.byName(name: "AWSLambdaRuntimeCore"),
7168
.product(name: "NIOTestUtils", package: "swift-nio"),
7269
.product(name: "NIOFoundationCompat", package: "swift-nio"),
73-
.product(name: "Testing", package: "swift-testing"),
7470
],
7571
swiftSettings: [.swiftLanguageMode(.v5)]
7672
),
@@ -79,7 +75,6 @@ let package = Package(
7975
dependencies: [
8076
.byName(name: "AWSLambdaRuntimeCore"),
8177
.byName(name: "AWSLambdaRuntime"),
82-
.product(name: "Testing", package: "swift-testing"),
8378
],
8479
swiftSettings: [.swiftLanguageMode(.v5)]
8580
),
@@ -95,8 +90,7 @@ let package = Package(
9590
.testTarget(
9691
name: "AWSLambdaTestingTests",
9792
dependencies: [
98-
.byName(name: "AWSLambdaTesting"),
99-
.product(name: "Testing", package: "swift-testing"),
93+
.byName(name: "AWSLambdaTesting")
10094
]
10195
),
10296
// for perf testing

Plugins/AWSLambdaPackager/PluginUtils.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ struct Utils {
3232

3333
let fd = dup(1)
3434
let stdout = fdopen(fd, "rw")
35-
defer { fclose(stdout) }
35+
defer { fclose(stdout!) }
3636

3737
// We need to use an unsafe transfer here to get the fd into our Sendable closure.
3838
// This transfer is fine, because we write to the variable from a single SerialDispatchQueue here.

Sources/AWSLambdaRuntime/Lambda+Codable.swift

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
@_exported import AWSLambdaRuntimeCore
1616
import NIOCore
17-
import NIOFoundationCompat
1817

1918
#if canImport(FoundationEssentials)
2019
import FoundationEssentials
@@ -24,7 +23,24 @@ import class Foundation.JSONDecoder
2423
import class Foundation.JSONEncoder
2524
#endif
2625

27-
extension JSONDecoder: AWSLambdaRuntimeCore.LambdaEventDecoder {}
26+
public struct LambdaJSONEventDecoder: LambdaEventDecoder {
27+
@usableFromInline let jsonDecoder: JSONDecoder
28+
29+
@inlinable
30+
public init(_ jsonDecoder: JSONDecoder) {
31+
self.jsonDecoder = jsonDecoder
32+
}
33+
34+
@inlinable
35+
public func decode<Event>(_ type: Event.Type, from buffer: NIOCore.ByteBuffer) throws -> Event where Event : Decodable {
36+
try buffer.getJSONDecodable(
37+
Event.self,
38+
decoder: self.jsonDecoder,
39+
at: buffer.readerIndex,
40+
length: buffer.readableBytes
41+
)! // must work, enough readable bytes
42+
}
43+
}
2844

2945
public struct LambdaJSONOutputEncoder<Output: Encodable>: LambdaOutputEncoder {
3046
@usableFromInline let jsonEncoder: JSONEncoder
@@ -36,15 +52,15 @@ public struct LambdaJSONOutputEncoder<Output: Encodable>: LambdaOutputEncoder {
3652

3753
@inlinable
3854
public func encode(_ value: Output, into buffer: inout ByteBuffer) throws {
39-
try self.jsonEncoder.encode(value, into: &buffer)
55+
try buffer.writeJSONEncodable(value, encoder: self.jsonEncoder)
4056
}
4157
}
4258

4359
extension LambdaCodableAdapter {
4460
/// Initializes an instance given an encoder, decoder, and a handler with a non-`Void` output.
4561
/// - Parameters:
46-
/// - encoder: The encoder object that will be used to encode the generic ``Output`` obtained from the `handler`'s `outputWriter` into a ``ByteBuffer``.
47-
/// - decoder: The decoder object that will be used to decode the received ``ByteBuffer`` event into the generic ``Event`` type served to the `handler`.
62+
/// - encoder: The encoder object that will be used to encode the generic `Output` obtained from the `handler`'s `outputWriter` into a `ByteBuffer`.
63+
/// - decoder: The decoder object that will be used to decode the received `ByteBuffer` event into the generic `Event` type served to the `handler`.
4864
/// - handler: The handler object.
4965
public init(
5066
encoder: JSONEncoder,
@@ -55,32 +71,33 @@ extension LambdaCodableAdapter {
5571
Output: Encodable,
5672
Output == Handler.Output,
5773
Encoder == LambdaJSONOutputEncoder<Output>,
58-
Decoder == JSONDecoder
74+
Decoder == LambdaJSONEventDecoder
5975
{
6076
self.init(
6177
encoder: LambdaJSONOutputEncoder(encoder),
62-
decoder: decoder,
78+
decoder: LambdaJSONEventDecoder(decoder),
6379
handler: handler
6480
)
6581
}
6682
}
6783

6884
extension LambdaRuntime {
69-
/// Initialize an instance with a ``LambdaHandler`` defined in the form of a closure **with a non-`Void` return type**.
70-
/// - Parameter body: The handler in the form of a closure.
71-
/// - Parameter encoder: The encoder object that will be used to encode the generic ``Output`` into a ``ByteBuffer``. ``JSONEncoder()`` used as default.
72-
/// - Parameter decoder: The decoder object that will be used to decode the incoming ``ByteBuffer`` event into the generic ``Event`` type. ``JSONDecoder()`` used as default.
85+
/// Initialize an instance with a `LambdaHandler` defined in the form of a closure **with a non-`Void` return type**.
86+
/// - Parameters:
87+
/// - decoder: The decoder object that will be used to decode the incoming `ByteBuffer` event into the generic `Event` type. `JSONDecoder()` used as default.
88+
/// - encoder: The encoder object that will be used to encode the generic `Output` into a `ByteBuffer`. `JSONEncoder()` used as default.
89+
/// - body: The handler in the form of a closure.
7390
public convenience init<Event: Decodable, Output>(
74-
body: @escaping (Event, LambdaContext) async throws -> Output,
91+
decoder: JSONDecoder = JSONDecoder(),
7592
encoder: JSONEncoder = JSONEncoder(),
76-
decoder: JSONDecoder = JSONDecoder()
93+
body: sending @escaping (Event, LambdaContext) async throws -> Output
7794
)
7895
where
7996
Handler == LambdaCodableAdapter<
8097
LambdaHandlerAdapter<Event, Output, ClosureHandler<Event, Output>>,
8198
Event,
8299
Output,
83-
JSONDecoder,
100+
LambdaJSONEventDecoder,
84101
LambdaJSONOutputEncoder<Output>
85102
>
86103
{
@@ -93,24 +110,24 @@ extension LambdaRuntime {
93110
self.init(handler: handler)
94111
}
95112

96-
/// Initialize an instance with a ``LambdaHandler`` defined in the form of a closure **with a `Void` return type**.
113+
/// Initialize an instance with a `LambdaHandler` defined in the form of a closure **with a `Void` return type**.
97114
/// - Parameter body: The handler in the form of a closure.
98-
/// - Parameter decoder: The decoder object that will be used to decode the incoming ``ByteBuffer`` event into the generic ``Event`` type. ``JSONDecoder()`` used as default.
115+
/// - Parameter decoder: The decoder object that will be used to decode the incoming `ByteBuffer` event into the generic `Event` type. `JSONDecoder()` used as default.
99116
public convenience init<Event: Decodable>(
100-
body: @escaping (Event, LambdaContext) async throws -> Void,
101-
decoder: JSONDecoder = JSONDecoder()
117+
decoder: JSONDecoder = JSONDecoder(),
118+
body: sending @escaping (Event, LambdaContext) async throws -> Void
102119
)
103120
where
104121
Handler == LambdaCodableAdapter<
105122
LambdaHandlerAdapter<Event, Void, ClosureHandler<Event, Void>>,
106123
Event,
107124
Void,
108-
JSONDecoder,
125+
LambdaJSONEventDecoder,
109126
VoidEncoder
110127
>
111128
{
112129
let handler = LambdaCodableAdapter(
113-
decoder: decoder,
130+
decoder: LambdaJSONEventDecoder(decoder),
114131
handler: LambdaHandlerAdapter(handler: ClosureHandler(body: body))
115132
)
116133

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftNIO open source project
4+
//
5+
// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO 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 SwiftNIO project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import Foundation
16+
import NIOCore
17+
18+
// This is NIO's `NIOFoundationCompat` module which at the moment only adds `ByteBuffer` utility methods
19+
// for Foundation's `Data` type.
20+
//
21+
// The reason that it's not in the `NIO` module is that we don't want to have any direct Foundation dependencies
22+
// in `NIO` as Foundation is problematic for a few reasons:
23+
//
24+
// - its implementation is different on Linux and on macOS which means our macOS tests might be inaccurate
25+
// - on macOS Foundation is mostly written in ObjC which means the autorelease pool might get populated
26+
// - `swift-corelibs-foundation` (the OSS Foundation used on Linux) links the world which will prevent anyone from
27+
// having static binaries. It can also cause problems in the choice of an SSL library as Foundation already brings
28+
// the platforms OpenSSL in which might cause problems.
29+
30+
extension ByteBuffer {
31+
/// Controls how bytes are transferred between `ByteBuffer` and other storage types.
32+
@usableFromInline
33+
enum ByteTransferStrategy: Sendable {
34+
/// Force a copy of the bytes.
35+
case copy
36+
37+
/// Do not copy the bytes if at all possible.
38+
case noCopy
39+
40+
/// Use a heuristic to decide whether to copy the bytes or not.
41+
case automatic
42+
}
43+
44+
// MARK: - Data APIs
45+
46+
/// Return `length` bytes starting at `index` and return the result as `Data`. This will not change the reader index.
47+
/// The selected bytes must be readable or else `nil` will be returned.
48+
///
49+
/// - parameters:
50+
/// - index: The starting index of the bytes of interest into the `ByteBuffer`
51+
/// - length: The number of bytes of interest
52+
/// - byteTransferStrategy: Controls how to transfer the bytes. See `ByteTransferStrategy` for an explanation
53+
/// of the options.
54+
/// - returns: A `Data` value containing the bytes of interest or `nil` if the selected bytes are not readable.
55+
@usableFromInline
56+
func getData(at index0: Int, length: Int, byteTransferStrategy: ByteTransferStrategy) -> Data? {
57+
let index = index0 - self.readerIndex
58+
guard index >= 0 && length >= 0 && index <= self.readableBytes - length else {
59+
return nil
60+
}
61+
let doCopy: Bool
62+
switch byteTransferStrategy {
63+
case .copy:
64+
doCopy = true
65+
case .noCopy:
66+
doCopy = false
67+
case .automatic:
68+
doCopy = length <= 256 * 1024
69+
}
70+
71+
return self.withUnsafeReadableBytesWithStorageManagement { ptr, storageRef in
72+
if doCopy {
73+
return Data(
74+
bytes: UnsafeMutableRawPointer(mutating: ptr.baseAddress!.advanced(by: index)),
75+
count: Int(length)
76+
)
77+
} else {
78+
_ = storageRef.retain()
79+
return Data(
80+
bytesNoCopy: UnsafeMutableRawPointer(mutating: ptr.baseAddress!.advanced(by: index)),
81+
count: Int(length),
82+
deallocator: .custom { _, _ in storageRef.release() }
83+
)
84+
}
85+
}
86+
}
87+
}

0 commit comments

Comments
 (0)