-
Notifications
You must be signed in to change notification settings - Fork 28
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
feat: Make models Sendable #829
base: main
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
import class Foundation.FileHandle | ||
import struct Foundation.Data | ||
|
||
public enum ByteStream { | ||
public enum ByteStream: Sendable { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This conformance is possible since |
||
case data(Data?) | ||
case stream(Stream) | ||
case noStream | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,8 +8,9 @@ | |
import struct Foundation.Data | ||
import struct Foundation.Date | ||
|
||
public protocol SmithyDocument { | ||
public protocol SmithyDocument: Sendable { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All of the |
||
|
||
/// The Smithy type corresponding to the data stored in this document. | ||
var type: ShapeType { get } | ||
|
||
// "as" methods throw if the document doesn't match the requested type. | ||
|
@@ -116,6 +117,20 @@ public extension SmithyDocument { | |
|
||
extension SmithyDocument { | ||
|
||
/// Compares two `SmithyDocument`-conforming values, checking for equality. | ||
/// | ||
/// Two `SmithyDocument`s are equal if they have the same type and equal values. | ||
/// | ||
/// Two Smithy `list` documents are equal if they have equal documents at every index. | ||
/// | ||
/// Two Smithy `map` documents are equal if they have the same set of keys, and equal values for every key. | ||
/// | ||
/// - note: Because `SmithyDocument` is a protocol, it cannot conform to `Equatable`; the type-erased | ||
/// container type ``Document`` is used to provide Smithy documents with equatability. | ||
/// - Parameters: | ||
/// - lhs: The first `SmithyDocument` to compare. | ||
/// - rhs: The second `SmithyDocument` to compare. | ||
/// - Returns: `true` if the two `SmithyDocument`s are equal, `false` otherwise. | ||
public static func isEqual(_ lhs: SmithyDocument, _ rhs: SmithyDocument) -> Bool { | ||
switch (lhs.type, rhs.type) { | ||
case (.blob, .blob): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,8 +16,8 @@ import class SmithyStreams.BufferedStream | |
/// URLSessionHTTPClient streams chunked payloads using this stream type. | ||
/// CRTClientEngine uses only the reader provided by this type to create chunks, then it | ||
/// streams them itself. | ||
public class ChunkedStream { | ||
private var inputStream: Stream | ||
public class ChunkedStream: @unchecked Sendable { | ||
private let inputStream: Stream | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Streams were designed to be thread-safe so they may be marked |
||
private var signingConfig: SigningConfig | ||
private var previousSignature: String | ||
private var trailingHeaders: Headers | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,10 +16,10 @@ | |
case invalidMessage(String) | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The extension below was unused and causing compiler warnings, so it was deleted. |
||
extension AsyncThrowingStream: Equatable where Element: Equatable { | ||
|
||
public static func == (lhs: AsyncThrowingStream, rhs: AsyncThrowingStream) -> Bool { | ||
// TODO: Remove as part of https://github.com/awslabs/aws-sdk-swift/issues/898 | ||
return false | ||
} | ||
} | ||
//extension AsyncThrowingStream: Equatable where Element: Equatable { | ||
// | ||
// public static func == (lhs: AsyncThrowingStream, rhs: AsyncThrowingStream) -> Bool { | ||
// // TODO: Remove as part of https://github.com/awslabs/aws-sdk-swift/issues/898 | ||
// return false | ||
// } | ||
//} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ | |
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
public struct Headers { | ||
public struct Headers: Sendable { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
public var headers: [Header] = [] | ||
|
||
/// Creates an empty instance. | ||
|
@@ -197,7 +197,7 @@ extension Array where Element == Header { | |
} | ||
} | ||
|
||
public struct Header { | ||
public struct Header: Sendable { | ||
public var name: String | ||
public var value: [String] | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,7 @@ import protocol Smithy.Stream | |
/// A `Stream` that wraps a `FileHandle` for reading the file. | ||
/// | ||
/// - Note: This class is thread-safe. | ||
public final class FileStream: Stream { | ||
public final class FileStream: Stream, @unchecked Sendable { | ||
|
||
/// Returns the length of the stream, if known | ||
public var length: Int? { | ||
|
@@ -26,7 +26,7 @@ public final class FileStream: Stream { | |
let fileHandle: FileHandle | ||
|
||
/// Returns the current position of the stream. | ||
public var position: Data.Index | ||
public private(set) var position: Data.Index | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Technically this is a breaking API change but it would cause a bug to alter this property from outside this type. |
||
|
||
/// Returns true if length is zero, false otherwise. | ||
public var isEmpty: Bool { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -143,8 +143,9 @@ class EnumGenerator( | |
writer.writeShapeDocs(shape) | ||
writer.writeAvailableAttribute(null, shape) | ||
writer.openBlock( | ||
"public enum \$enum.name:L: \$N, \$N, \$N, \$N {", | ||
"public enum \$enum.name:L: \$N, \$N, \$N, \$N, \$N {", | ||
"}", | ||
SwiftTypes.Protocols.Sendable, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mark generated |
||
SwiftTypes.Protocols.Equatable, | ||
SwiftTypes.Protocols.RawRepresentable, | ||
SwiftTypes.Protocols.CaseIterable, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,7 @@ class IntEnumGenerator( | |
if (isNestedType) { | ||
val service = model.expectShape<ServiceShape>(settings.service) | ||
writer.openBlock("extension ${service.nestedNamespaceType(symbolProvider)} {", "}") { | ||
writer.write("") | ||
renderEnum() | ||
} | ||
} else { | ||
|
@@ -41,8 +42,9 @@ class IntEnumGenerator( | |
writer.writeShapeDocs(shape) | ||
writer.writeAvailableAttribute(null, shape) | ||
writer.openBlock( | ||
"public enum \$enum.name:L: \$N, \$N, \$N, \$N {", | ||
"public enum \$enum.name:L: \$N, \$N, \$N, \$N, \$N {", | ||
"}", | ||
SwiftTypes.Protocols.Sendable, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mark generated Also adjust spacing a bit. |
||
SwiftTypes.Protocols.Equatable, | ||
SwiftTypes.Protocols.RawRepresentable, | ||
SwiftTypes.Protocols.CaseIterable, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -113,15 +113,15 @@ class StructureGenerator( | |
} | ||
|
||
private fun generateStruct() { | ||
writer.write("") | ||
writer.writeShapeDocs(shape) | ||
writer.writeAvailableAttribute(model, shape) | ||
val equatableConformance = writer.format(": \$N ", SwiftTypes.Protocols.Equatable).takeIf { shape.hasTrait<EquatableConformanceTrait>() } ?: "" | ||
writer.openBlock("public struct \$struct.name:L $equatableConformance{") | ||
val equatableConformance = writer.format(", \$N", SwiftTypes.Protocols.Equatable).takeIf { shape.hasTrait<EquatableConformanceTrait>() } ?: "" | ||
writer.openBlock("public struct \$struct.name:L: \$N$equatableConformance {", SwiftTypes.Protocols.Sendable) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mark generated Also adjust spacing of generated code. |
||
.call { generateStructMembers() } | ||
.write("") | ||
.call { generateInitializerForStructure(false) } | ||
.closeBlock("}") | ||
.write("") | ||
} | ||
|
||
private fun generateStructMembers() { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,6 +64,7 @@ class UnionGenerator( | |
if (isNestedType) { | ||
val service = model.expectShape<ServiceShape>(settings.service) | ||
writer.openBlock("extension ${service.nestedNamespaceType(symbolProvider)} {", "}") { | ||
writer.write("") | ||
renderUnion() | ||
} | ||
} else { | ||
|
@@ -76,8 +77,8 @@ class UnionGenerator( | |
writer.writeShapeDocs(shape) | ||
writer.writeAvailableAttribute(model, shape) | ||
val indirectOrNot = "indirect ".takeIf { shape.hasTrait<RecursiveUnionTrait>() } ?: "" | ||
val equatableConformance = (": " + SwiftTypes.Protocols.Equatable + " ").takeIf { shape.hasTrait<EquatableConformanceTrait>() } ?: "" | ||
writer.openBlock("public ${indirectOrNot}enum \$union.name:L $equatableConformance{", "}\n") { | ||
val equatableConformance = writer.format(", \$N", SwiftTypes.Protocols.Equatable).takeIf { shape.hasTrait<EquatableConformanceTrait>() } ?: "" | ||
writer.openBlock("public ${indirectOrNot}enum \$union.name:L: \$N$equatableConformance {", "}", SwiftTypes.Protocols.Sendable) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mark generated Also adjust formatting. |
||
// event streams (@streaming union) MAY have variants that target errors. | ||
// These errors if encountered on the stream will be thrown as an exception rather | ||
// than showing up as one of the possible events the consumer will see on the stream (AsyncThrowingStream<T>). | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ object SwiftTypes { | |
val RawRepresentable = builtInSymbol("RawRepresentable", SwiftDeclaration.PROTOCOL) | ||
val CaseIterable = builtInSymbol("CaseIterable", SwiftDeclaration.PROTOCOL) | ||
val CustomDebugStringConvertible = builtInSymbol("CustomDebugStringConvertible", SwiftDeclaration.PROTOCOL) | ||
val Sendable = builtInSymbol("Sendable", SwiftDeclaration.PROTOCOL) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,7 +39,7 @@ class EnumGeneratorTests { | |
|
||
val expectedGeneratedEnum = """ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Below changes are Kotlin codegen tests. Changes in test expectations:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try turning off whitespace changes on the Github diff to see the more substantial part of the test changes. |
||
/// Really long multi-line Documentation for the enum | ||
public enum MyEnum: Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { | ||
public enum MyEnum: Swift.Sendable, Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { | ||
/// Documentation for BAR | ||
case bar | ||
case fooBazXap | ||
|
@@ -98,7 +98,7 @@ public enum MyEnum: Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, | |
|
||
val expectedGeneratedEnum = """ | ||
/// Really long multi-line Documentation for the enum | ||
public enum MyEnum: Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { | ||
public enum MyEnum: Swift.Sendable, Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { | ||
/// ""${'"'} T2 instances are Burstable Performance Instances that provide a baseline level of CPU performance with the ability to burst above the baseline.""${'"'} | ||
case t2Micro | ||
case t2Nano | ||
|
@@ -141,7 +141,7 @@ public enum MyEnum: Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, | |
var expectedGeneratedEnum = """ | ||
extension ExampleClientTypes { | ||
|
||
public enum Suit: Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { | ||
public enum Suit: Swift.Sendable, Swift.Equatable, Swift.RawRepresentable, Swift.CaseIterable, Swift.Hashable { | ||
case club | ||
case diamond | ||
case heart | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This property wrapper is mostly same as before, but now stores its value in private storage that is protected by a lock when getting & setting.
Since it enforces exclusive access to its wrapped value, it can now be
Sendable
.