Skip to content

Commit 8823358

Browse files
authored
Merge branch 'main' into fix-docs-typo
2 parents 05057fb + c47ee1b commit 8823358

File tree

5 files changed

+62
-18
lines changed

5 files changed

+62
-18
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ jobs:
1414
linux_5_9_enabled: false
1515
linux_5_10_enabled: false
1616
linux_6_0_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
17+
linux_6_1_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
1718
linux_nightly_next_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
1819
linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
1920

.github/workflows/pull_request.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ jobs:
2323
linux_5_9_enabled: false
2424
linux_5_10_enabled: false
2525
linux_6_0_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
26+
linux_6_1_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
2627
linux_nightly_next_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
2728
linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
2829

Sources/GRPCProtobuf/Errors/GoogleRPCStatus.swift

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
public import GRPCCore
18-
internal import SwiftProtobuf
18+
public import SwiftProtobuf
1919

2020
/// An error containing structured details which can be delivered to the client.
2121
///
@@ -74,31 +74,63 @@ public struct GoogleRPCStatus: Error {
7474
}
7575
}
7676

77-
extension GoogleRPCStatus: GoogleProtobufAnyPackable {
78-
// See https://protobuf.dev/programming-guides/proto3/#any
79-
internal static var typeURL: String { "type.googleapis.com/google.rpc.Status" }
80-
81-
init?(unpacking any: Google_Protobuf_Any) throws {
82-
guard any.isA(Google_Rpc_Status.self) else { return nil }
83-
let status = try Google_Rpc_Status(serializedBytes: any.value)
77+
extension GoogleRPCStatus {
78+
/// Creates a new message by decoding the given `SwiftProtobufContiguousBytes` value
79+
/// containing a serialized message in Protocol Buffer binary format.
80+
///
81+
/// - Parameters:
82+
/// - bytes: The binary-encoded message data to decode.
83+
/// - extensions: An `ExtensionMap` used to look up and decode any
84+
/// extensions in this message or messages nested within this message's
85+
/// fields.
86+
/// - partial: If `false` (the default), this method will check if the `Message`
87+
/// is initialized after decoding to verify that all required fields are present.
88+
/// If any are missing, this method throws `BinaryDecodingError`.
89+
/// - options: The `BinaryDecodingOptions` to use.
90+
/// - Throws: `BinaryDecodingError` if decoding fails.
91+
public init<Bytes: SwiftProtobufContiguousBytes>(
92+
serializedBytes bytes: Bytes,
93+
extensions: (any ExtensionMap)? = nil,
94+
partial: Bool = false,
95+
options: BinaryDecodingOptions = BinaryDecodingOptions()
96+
) throws {
97+
let status = try Google_Rpc_Status(
98+
serializedBytes: bytes,
99+
extensions: extensions,
100+
partial: partial,
101+
options: options
102+
)
84103

85104
let statusCode = Status.Code(rawValue: Int(status.code))
86105
self.code = statusCode.flatMap { RPCError.Code($0) } ?? .unknown
87106
self.message = status.message
88107
self.details = try status.details.map { try ErrorDetails(unpacking: $0) }
89108
}
90109

91-
func pack() throws -> Google_Protobuf_Any {
110+
/// Returns a `SwiftProtobufContiguousBytes` instance containing the Protocol Buffer binary
111+
/// format serialization of the message.
112+
///
113+
/// - Parameters:
114+
/// - partial: If `false` (the default), this method will check
115+
/// `Message.isInitialized` before encoding to verify that all required
116+
/// fields are present. If any are missing, this method throws.
117+
/// `BinaryEncodingError/missingRequiredFields`.
118+
/// - options: The `BinaryEncodingOptions` to use.
119+
/// - Returns: A `SwiftProtobufContiguousBytes` instance containing the binary serialization
120+
/// of the message.
121+
///
122+
/// - Throws: `SwiftProtobufError` or `BinaryEncodingError` if encoding fails.
123+
public func serializedBytes<Bytes: SwiftProtobufContiguousBytes>(
124+
partial: Bool = false,
125+
options: BinaryEncodingOptions = BinaryEncodingOptions()
126+
) throws -> Bytes {
92127
let status = try Google_Rpc_Status.with {
93128
$0.code = Int32(self.code.rawValue)
94129
$0.message = self.message
95130
$0.details = try self.details.map { try $0.pack() }
96131
}
97132

98-
return try .with {
99-
$0.typeURL = Self.typeURL
100-
$0.value = try status.serializedBytes()
101-
}
133+
return try status.serializedBytes(partial: partial, options: options)
102134
}
103135
}
104136

@@ -107,8 +139,7 @@ extension GoogleRPCStatus: RPCErrorConvertible {
107139
public var rpcErrorMessage: String { self.message }
108140
public var rpcErrorMetadata: Metadata {
109141
do {
110-
let any = try self.pack()
111-
let bytes: [UInt8] = try any.serializedBytes()
142+
let bytes: [UInt8] = try self.serializedBytes()
112143
return [Metadata.statusDetailsBinKey: .binary(bytes)]
113144
} catch {
114145
// Failed to serialize error details. Not a lot can be done here.

Sources/GRPCProtobuf/Errors/RPCError+GoogleRPCStatus.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ extension RPCError {
3131
public func unpackGoogleRPCStatus() throws -> GoogleRPCStatus? {
3232
let values = self.metadata[binaryValues: Metadata.statusDetailsBinKey]
3333
guard let bytes = values.first(where: { _ in true }) else { return nil }
34-
35-
let any = try Google_Protobuf_Any(serializedBytes: bytes)
36-
return try GoogleRPCStatus(unpacking: any)
34+
return try GoogleRPCStatus(serializedBytes: bytes)
3735
}
3836
}

Tests/GRPCProtobufTests/Errors/DetailedErrorTests.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,19 @@ struct DetailedErrorTests {
9898
func errorInfoDescription(_ details: ErrorDetails, expected: String) {
9999
#expect(String(describing: details) == expected)
100100
}
101+
102+
@Test("Round-trip encoding of GoogleRPCStatus")
103+
func googleRPCStatusRoundTripCoding() throws {
104+
let detail = ErrorDetails.BadRequest(violations: [.init(field: "foo", description: "bar")])
105+
let status = GoogleRPCStatus(code: .dataLoss, message: "Uh oh", details: [.badRequest(detail)])
106+
107+
let serialized: [UInt8] = try status.serializedBytes()
108+
let deserialized = try GoogleRPCStatus(serializedBytes: serialized)
109+
#expect(deserialized.code == status.code)
110+
#expect(deserialized.message == status.message)
111+
#expect(deserialized.details.count == status.details.count)
112+
#expect(deserialized.details.first?.badRequest == detail)
113+
}
101114
}
102115

103116
private struct ErrorThrowingService: ErrorService.SimpleServiceProtocol {

0 commit comments

Comments
 (0)