Skip to content

Commit 9bed141

Browse files
authored
Add deprecation warnings for package-internal APIs (#315)
This PR adds deprecation warnings to APIs that are considered package-internal but cannot yet be marked as `package` instead of `public` until we adopt Swift 6 (see #310). We can't make these APIs _currently_ deprecated since that will introduce deprecation warnings where they're used within the library, but we can at least add _future deprecation_ warnings which will show up in the IDE as shown below: <img width="684" alt="Screenshot 2024-10-16 at 11 27 45 AM" src="https://github.com/user-attachments/assets/be489f7f-bf32-466d-8aa3-1fc999bba0c6"> The goal of doing this is to help enable us to tag a 1.0 before adopting Swift 6 so we can mark those APIs as `package` afterwards and reasonably consider it a non-breaking change. --------- Signed-off-by: Michael Rebello <[email protected]>
1 parent 69661a2 commit 9bed141

File tree

9 files changed

+106
-61
lines changed

9 files changed

+106
-61
lines changed

Libraries/Connect/Internal/Interceptors/ConnectInterceptor.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ extension ConnectInterceptor: StreamInterceptor {
158158

159159
@Sendable
160160
func handleStreamRawInput(_ input: Data, proceed: @escaping (Data) -> Void) {
161-
proceed(Envelope.packMessage(input, using: self.config.requestCompression))
161+
proceed(Envelope._packMessage(input, using: self.config.requestCompression))
162162
}
163163

164164
@Sendable
@@ -190,7 +190,7 @@ extension ConnectInterceptor: StreamInterceptor {
190190
let responseCompressionPool = self.streamResponseHeaders.value?[
191191
HeaderConstants.connectStreamingContentEncoding
192192
]?.first.flatMap { self.config.responseCompressionPool(forName: $0) }
193-
if responseCompressionPool == nil && Envelope.isCompressed(data) {
193+
if responseCompressionPool == nil && Envelope._isCompressed(data) {
194194
proceed(.complete(
195195
code: .internalError, error: ConnectError(
196196
code: .internalError, message: "received unexpected compressed message"
@@ -199,7 +199,7 @@ extension ConnectInterceptor: StreamInterceptor {
199199
return
200200
}
201201

202-
let (headerByte, message) = try Envelope.unpackMessage(
202+
let (headerByte, message) = try Envelope._unpackMessage(
203203
data, compressionPool: responseCompressionPool
204204
)
205205
let isEndStream = 0b00000010 & headerByte != 0

Libraries/Connect/Internal/Interceptors/GRPCWebInterceptor.swift

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ extension GRPCWebInterceptor: UnaryInterceptor {
3232
proceed: @escaping (Result<HTTPRequest<Data?>, ConnectError>) -> Void
3333
) {
3434
// gRPC-Web unary payloads are enveloped.
35-
let envelopedRequestBody = Envelope.packMessage(
35+
let envelopedRequestBody = Envelope._packMessage(
3636
request.message ?? Data(), using: self.config.requestCompression
3737
)
3838
proceed(.success(HTTPRequest(
3939
url: request.url,
40-
headers: request.headers.addingGRPCHeaders(using: self.config, grpcWeb: true),
40+
headers: request.headers._addingGRPCHeaders(using: self.config, grpcWeb: true),
4141
message: envelopedRequestBody,
4242
method: request.method,
4343
trailers: nil,
@@ -57,7 +57,7 @@ extension GRPCWebInterceptor: UnaryInterceptor {
5757
}
5858

5959
guard let responseData = response.message, !responseData.isEmpty else {
60-
let (grpcCode, connectError) = ConnectError.parseGRPCHeaders(
60+
let (grpcCode, connectError) = ConnectError._parseGRPCHeaders(
6161
response.headers,
6262
trailers: response.trailers
6363
)
@@ -102,7 +102,7 @@ extension GRPCWebInterceptor: UnaryInterceptor {
102102
let compressionPool = response.headers[HeaderConstants.grpcContentEncoding]?
103103
.first
104104
.flatMap { self.config.responseCompressionPool(forName: $0) }
105-
if compressionPool == nil && Envelope.isCompressed(responseData) {
105+
if compressionPool == nil && Envelope._isCompressed(responseData) {
106106
proceed(HTTPResponse(
107107
code: .internalError, headers: response.headers, message: nil,
108108
trailers: response.trailers,
@@ -120,9 +120,9 @@ extension GRPCWebInterceptor: UnaryInterceptor {
120120
// message data.
121121
// 2. The (headers and length prefixed) trailers data.
122122
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md
123-
let firstChunkLength = Envelope.messageLength(forPackedData: responseData)
124-
let prefixedFirstChunkLength = Envelope.prefixLength + firstChunkLength
125-
let firstChunk = try Envelope.unpackMessage(
123+
let firstChunkLength = Envelope._messageLength(forPackedData: responseData)
124+
let prefixedFirstChunkLength = Envelope._prefixLength + firstChunkLength
125+
let firstChunk = try Envelope._unpackMessage(
126126
Data(responseData.prefix(upTo: prefixedFirstChunkLength)),
127127
compressionPool: compressionPool
128128
)
@@ -135,7 +135,7 @@ extension GRPCWebInterceptor: UnaryInterceptor {
135135
} else {
136136
let trailersData = Data(responseData.suffix(from: prefixedFirstChunkLength))
137137
let unpackedTrailers = try Trailers.fromGRPCHeadersBlock(
138-
try Envelope.unpackMessage(
138+
try Envelope._unpackMessage(
139139
trailersData, compressionPool: compressionPool
140140
).unpacked
141141
)
@@ -165,7 +165,7 @@ extension GRPCWebInterceptor: StreamInterceptor {
165165
) {
166166
proceed(.success(HTTPRequest(
167167
url: request.url,
168-
headers: request.headers.addingGRPCHeaders(using: self.config, grpcWeb: true),
168+
headers: request.headers._addingGRPCHeaders(using: self.config, grpcWeb: true),
169169
message: request.message,
170170
method: request.method,
171171
trailers: nil,
@@ -175,7 +175,7 @@ extension GRPCWebInterceptor: StreamInterceptor {
175175

176176
@Sendable
177177
func handleStreamRawInput(_ input: Data, proceed: @escaping (Data) -> Void) {
178-
proceed(Envelope.packMessage(input, using: self.config.requestCompression))
178+
proceed(Envelope._packMessage(input, using: self.config.requestCompression))
179179
}
180180

181181
@Sendable
@@ -198,11 +198,11 @@ extension GRPCWebInterceptor: StreamInterceptor {
198198
return
199199
}
200200

201-
if let grpcCode = headers.grpcStatus() {
201+
if let grpcCode = headers._grpcStatus() {
202202
// Headers-only response.
203203
proceed(.complete(
204204
code: grpcCode,
205-
error: ConnectError.parseGRPCHeaders(nil, trailers: headers).error,
205+
error: ConnectError._parseGRPCHeaders(nil, trailers: headers).error,
206206
trailers: headers
207207
))
208208
} else {
@@ -215,13 +215,13 @@ extension GRPCWebInterceptor: StreamInterceptor {
215215
let responseCompressionPool = self.streamResponseHeaders.value?[
216216
HeaderConstants.grpcContentEncoding
217217
]?.first.flatMap { self.config.responseCompressionPool(forName: $0) }
218-
let (headerByte, unpackedData) = try Envelope.unpackMessage(
218+
let (headerByte, unpackedData) = try Envelope._unpackMessage(
219219
data, compressionPool: responseCompressionPool
220220
)
221221
let isTrailers = 0b10000000 & headerByte != 0
222222
if isTrailers {
223223
let trailers = try Trailers.fromGRPCHeadersBlock(unpackedData)
224-
let (grpcCode, error) = ConnectError.parseGRPCHeaders(
224+
let (grpcCode, error) = ConnectError._parseGRPCHeaders(
225225
self.streamResponseHeaders.value, trailers: trailers
226226
)
227227
if grpcCode == .ok {
@@ -290,7 +290,7 @@ private extension Trailers {
290290

291291
private extension HTTPResponse {
292292
func withHandledGRPCWebTrailers(_ trailers: Trailers, message: Data?) -> Self {
293-
let (grpcCode, error) = ConnectError.parseGRPCHeaders(self.headers, trailers: trailers)
293+
let (grpcCode, error) = ConnectError._parseGRPCHeaders(self.headers, trailers: trailers)
294294
if grpcCode != .ok || error != nil {
295295
return HTTPResponse(
296296
// Rewrite the gRPC code if it is "ok" but `connectError` is non-nil.

Libraries/Connect/PackageInternal/ConnectError+GRPC.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,16 @@ extension ConnectError {
2525
/// passed in the headers block for gRPC-Web.
2626
///
2727
/// - returns: A tuple containing the gRPC status code and an optional error.
28-
public static func parseGRPCHeaders(
28+
@available(
29+
swift,
30+
deprecated: 100.0,
31+
message: "This is an internal-only API which will be made package-private in Swift 6."
32+
)
33+
public static func _parseGRPCHeaders(
2934
_ headers: Headers?, trailers: Trailers?
3035
) -> (grpcCode: Code, error: ConnectError?) {
3136
// "Trailers-only" responses can be sent in the headers or trailers block.
32-
guard let grpcCode = trailers?.grpcStatus() ?? headers?.grpcStatus() else {
37+
guard let grpcCode = trailers?._grpcStatus() ?? headers?._grpcStatus() else {
3338
return (.unknown, ConnectError(code: .unknown, message: "RPC response missing status"))
3439
}
3540

Libraries/Connect/PackageInternal/Envelope.swift

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,19 @@ import SwiftProtobuf
1919
/// to change. When the compiler supports it, this should be package-internal.**
2020
///
2121
/// Provides functionality for packing and unpacking (headers and length prefixed) messages.
22+
@available(
23+
swift,
24+
deprecated: 100.0,
25+
message: "This is an internal-only API which will be made package-private in Swift 6."
26+
)
2227
public enum Envelope {
2328
/// The total number of bytes that will prefix a message.
24-
public static var prefixLength: Int {
29+
@available(
30+
swift,
31+
deprecated: 100.0,
32+
message: "This is an internal-only API which will be made package-private in Swift 6."
33+
)
34+
public static var _prefixLength: Int {
2535
return 5 // Header flags (1 byte) + message length (4 bytes)
2636
}
2737

@@ -35,7 +45,12 @@ public enum Envelope {
3545
/// - parameter compression: Configuration to use for compressing the message.
3646
///
3747
/// - returns: Serialized/enveloped data for transmission.
38-
public static func packMessage(
48+
@available(
49+
swift,
50+
deprecated: 100.0,
51+
message: "This is an internal-only API which will be made package-private in Swift 6."
52+
)
53+
public static func _packMessage(
3954
_ source: Data, using compression: ProtocolClientConfig.RequestCompression?
4055
) -> Data {
4156
var buffer = Data()
@@ -70,7 +85,12 @@ public enum Envelope {
7085
///
7186
/// - returns: A tuple that includes the header byte and the un-prefixed and decompressed
7287
/// message.
73-
public static func unpackMessage(
88+
@available(
89+
swift,
90+
deprecated: 100.0,
91+
message: "This is an internal-only API which will be made package-private in Swift 6."
92+
)
93+
public static func _unpackMessage(
7494
_ source: Data, compressionPool: CompressionPool?
7595
) throws -> (headerByte: UInt8, unpacked: Data) {
7696
if source.isEmpty {
@@ -79,7 +99,7 @@ public enum Envelope {
7999

80100
let headerByte = source[0]
81101
let isCompressed = 0b00000001 & headerByte != 0
82-
let messageData = Data(source.dropFirst(self.prefixLength))
102+
let messageData = Data(source.dropFirst(self._prefixLength))
83103
if isCompressed {
84104
guard let compressionPool = compressionPool else {
85105
throw Error.missingExpectedCompressionPool
@@ -96,7 +116,12 @@ public enum Envelope {
96116
/// - parameter packedData: The packed data to analyze.
97117
///
98118
/// - returns: True if the data is compressed.
99-
public static func isCompressed(_ packedData: Data) -> Bool {
119+
@available(
120+
swift,
121+
deprecated: 100.0,
122+
message: "This is an internal-only API which will be made package-private in Swift 6."
123+
)
124+
public static func _isCompressed(_ packedData: Data) -> Bool {
100125
return !packedData.isEmpty && (0b00000001 & packedData[0] != 0)
101126
}
102127

@@ -111,8 +136,13 @@ public enum Envelope {
111136
/// - returns: The length of the next expected message in the packed data. If multiple chunks
112137
/// are specified, this will return the length of the first. Returns -1 if there is
113138
/// not enough prefix data to determine the message length.
114-
public static func messageLength(forPackedData data: Data) -> Int {
115-
guard data.count >= self.prefixLength else {
139+
@available(
140+
swift,
141+
deprecated: 100.0,
142+
message: "This is an internal-only API which will be made package-private in Swift 6."
143+
)
144+
public static func _messageLength(forPackedData data: Data) -> Int {
145+
guard data.count >= self._prefixLength else {
116146
return -1
117147
}
118148

Libraries/Connect/PackageInternal/Headers+GRPC.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,12 @@ extension Headers {
2525
/// - parameter grpcWeb: Should be true if using gRPC-Web, false if gRPC.
2626
///
2727
/// - returns: A set of updated headers.
28-
public func addingGRPCHeaders(using config: ProtocolClientConfig, grpcWeb: Bool) -> Self {
28+
@available(
29+
swift,
30+
deprecated: 100.0,
31+
message: "This is an internal-only API which will be made package-private in Swift 6."
32+
)
33+
public func _addingGRPCHeaders(using config: ProtocolClientConfig, grpcWeb: Bool) -> Self {
2934
var headers = self
3035
headers[HeaderConstants.grpcAcceptEncoding] = config
3136
.acceptCompressionPoolNames()

Libraries/Connect/PackageInternal/Trailers+gRPC.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@ extension Trailers {
1919
/// Identifies the status code from gRPC and gRPC-Web trailers.
2020
///
2121
/// - returns: The gRPC status code, if specified.
22-
public func grpcStatus() -> Code? {
22+
@available(
23+
swift,
24+
deprecated: 100.0,
25+
message: "This is an internal-only API which will be made package-private in Swift 6."
26+
)
27+
public func _grpcStatus() -> Code? {
2328
return self[HeaderConstants.grpcStatus]?
2429
.first
2530
.flatMap(Int.init)

Libraries/Connect/Public/Implementation/Clients/ProtocolClient.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,12 +299,12 @@ extension ProtocolClient: ProtocolClientInterface {
299299
// Handle cases where multiple messages are received in a single chunk.
300300
responseBuffer += data
301301
while true {
302-
let messageLength = Envelope.messageLength(forPackedData: responseBuffer)
302+
let messageLength = Envelope._messageLength(forPackedData: responseBuffer)
303303
if messageLength < 0 {
304304
return
305305
}
306306

307-
let prefixedMessageLength = Envelope.prefixLength + messageLength
307+
let prefixedMessageLength = Envelope._prefixLength + messageLength
308308
guard responseBuffer.count >= prefixedMessageLength else {
309309
return
310310
}

Libraries/ConnectNIO/Internal/GRPCInterceptor.swift

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ extension GRPCInterceptor: UnaryInterceptor {
3434
proceed: @escaping (Result<HTTPRequest<Data?>, ConnectError>) -> Void
3535
) {
3636
// gRPC unary payloads are enveloped.
37-
let envelopedRequestBody = Envelope.packMessage(
37+
let envelopedRequestBody = Envelope._packMessage(
3838
request.message ?? Data(), using: self.config.requestCompression
3939
)
4040

4141
proceed(.success(HTTPRequest(
4242
url: request.url,
43-
headers: request.headers.addingGRPCHeaders(using: self.config, grpcWeb: false),
43+
headers: request.headers._addingGRPCHeaders(using: self.config, grpcWeb: false),
4444
message: envelopedRequestBody,
4545
method: request.method,
4646
trailers: nil,
@@ -72,12 +72,12 @@ extension GRPCInterceptor: UnaryInterceptor {
7272
return
7373
}
7474

75-
let (grpcCode, connectError) = ConnectError.parseGRPCHeaders(
75+
let (grpcCode, connectError) = ConnectError._parseGRPCHeaders(
7676
response.headers,
7777
trailers: response.trailers
7878
)
7979
guard grpcCode == .ok, let rawData = response.message, !rawData.isEmpty else {
80-
if response.trailers.grpcStatus() == nil && response.message?.isEmpty == false {
80+
if response.trailers._grpcStatus() == nil && response.message?.isEmpty == false {
8181
proceed(HTTPResponse(
8282
code: .internalError,
8383
headers: response.headers,
@@ -117,7 +117,7 @@ extension GRPCInterceptor: UnaryInterceptor {
117117
.headers[HeaderConstants.grpcContentEncoding]?
118118
.first
119119
.flatMap { self.config.responseCompressionPool(forName: $0) }
120-
if compressionPool == nil && Envelope.isCompressed(rawData) {
120+
if compressionPool == nil && Envelope._isCompressed(rawData) {
121121
proceed(HTTPResponse(
122122
code: .internalError, headers: response.headers, message: nil,
123123
trailers: response.trailers, error: ConnectError(
@@ -140,7 +140,7 @@ extension GRPCInterceptor: UnaryInterceptor {
140140
}
141141

142142
do {
143-
let messageData = try Envelope.unpackMessage(
143+
let messageData = try Envelope._unpackMessage(
144144
rawData, compressionPool: compressionPool
145145
).unpacked
146146
proceed(HTTPResponse(
@@ -172,7 +172,7 @@ extension GRPCInterceptor: StreamInterceptor {
172172
) {
173173
proceed(.success(HTTPRequest(
174174
url: request.url,
175-
headers: request.headers.addingGRPCHeaders(using: self.config, grpcWeb: false),
175+
headers: request.headers._addingGRPCHeaders(using: self.config, grpcWeb: false),
176176
message: request.message,
177177
method: request.method,
178178
trailers: nil,
@@ -182,7 +182,7 @@ extension GRPCInterceptor: StreamInterceptor {
182182

183183
@Sendable
184184
func handleStreamRawInput(_ input: Data, proceed: @escaping (Data) -> Void) {
185-
proceed(Envelope.packMessage(input, using: self.config.requestCompression))
185+
proceed(Envelope._packMessage(input, using: self.config.requestCompression))
186186
}
187187

188188
@Sendable
@@ -214,7 +214,7 @@ extension GRPCInterceptor: StreamInterceptor {
214214
let responseCompressionPool = self.streamResponseHeaders.value?[
215215
HeaderConstants.grpcContentEncoding
216216
]?.first.flatMap { self.config.responseCompressionPool(forName: $0) }
217-
if responseCompressionPool == nil && Envelope.isCompressed(rawData) {
217+
if responseCompressionPool == nil && Envelope._isCompressed(rawData) {
218218
proceed(.complete(
219219
code: .internalError, error: ConnectError(
220220
code: .internalError, message: "received unexpected compressed message"
@@ -223,7 +223,7 @@ extension GRPCInterceptor: StreamInterceptor {
223223
return
224224
}
225225

226-
let unpackedMessage = try Envelope.unpackMessage(
226+
let unpackedMessage = try Envelope._unpackMessage(
227227
rawData, compressionPool: responseCompressionPool
228228
).unpacked
229229
proceed(.message(unpackedMessage))
@@ -239,7 +239,7 @@ extension GRPCInterceptor: StreamInterceptor {
239239
return
240240
}
241241

242-
let (grpcCode, connectError) = ConnectError.parseGRPCHeaders(
242+
let (grpcCode, connectError) = ConnectError._parseGRPCHeaders(
243243
self.streamResponseHeaders.value,
244244
trailers: trailers
245245
)
@@ -275,8 +275,8 @@ extension GRPCInterceptor: StreamInterceptor {
275275

276276
private extension Envelope {
277277
static func containsMultipleGRPCMessages(_ packedData: Data) -> Bool {
278-
let messageLength = self.messageLength(forPackedData: packedData)
279-
return packedData.count > messageLength + self.prefixLength
278+
let messageLength = self._messageLength(forPackedData: packedData)
279+
return packedData.count > messageLength + self._prefixLength
280280
}
281281
}
282282

0 commit comments

Comments
 (0)