Browse Source

Allow padding to be omitted from binary metadata values (#2243)

Motivation:

Binary metadata values are encoded as base64 strings. The gRPC spec
doesn't require that the values are padded. Currently gRPC Swift
requires values to be padded otherwise decoding will fail.

Modifications:

- Allow padding characters to be omitted when decoding base64

Result:

Can decode unpadded binary metadata values
George Barnett 8 months ago
parent
commit
36e1ad1d86

+ 1 - 5
IntegrationTests/Benchmarks/Thresholds/6.0/GRPCSwiftBenchmark.Metadata_Iterate_binary_values_when_only_strings_stored.p90.json

@@ -1,7 +1,3 @@
 {
 {
-  "mallocCountTotal" : 2000,
-  "memoryLeaked" : 0,
-  "releaseCount" : 6001,
-  "retainCount" : 2000,
-  "syscalls" : 0
+  "mallocCountTotal": 1000
 }
 }

+ 1 - 5
IntegrationTests/Benchmarks/Thresholds/6.1/GRPCSwiftBenchmark.Metadata_Iterate_binary_values_when_only_strings_stored.p90.json

@@ -1,7 +1,3 @@
 {
 {
-  "mallocCountTotal" : 2000,
-  "memoryLeaked" : 0,
-  "releaseCount" : 6001,
-  "retainCount" : 2000,
-  "syscalls" : 0
+  "mallocCountTotal": 1000
 }
 }

+ 1 - 5
IntegrationTests/Benchmarks/Thresholds/nightly-main/GRPCSwiftBenchmark.Metadata_Iterate_binary_values_when_only_strings_stored.p90.json

@@ -1,7 +1,3 @@
 {
 {
-  "mallocCountTotal" : 2000,
-  "memoryLeaked" : 0,
-  "releaseCount" : 7001,
-  "retainCount" : 3000,
-  "syscalls" : 0
+  "mallocCountTotal": 1000
 }
 }

+ 1 - 5
IntegrationTests/Benchmarks/Thresholds/nightly-next/GRPCSwiftBenchmark.Metadata_Iterate_binary_values_when_only_strings_stored.p90.json

@@ -1,7 +1,3 @@
 {
 {
-  "mallocCountTotal" : 2000,
-  "memoryLeaked" : 0,
-  "releaseCount" : 7001,
-  "retainCount" : 3000,
-  "syscalls" : 0
+  "mallocCountTotal": 1000
 }
 }

+ 1 - 1
Sources/GRPCCore/Metadata.swift

@@ -423,7 +423,7 @@ extension Metadata {
           switch value {
           switch value {
           case .string(let stringValue):
           case .string(let stringValue):
             do {
             do {
-              return try Base64.decode(string: stringValue)
+              return try Base64.decode(string: stringValue, options: [.omitPaddingCharacter])
             } catch {
             } catch {
               continue
               continue
             }
             }

+ 12 - 0
Tests/GRPCCoreTests/MetadataTests.swift

@@ -221,6 +221,18 @@ struct MetadataTests {
     #expect(Array(metadata[binaryValues: "key-bin"]) == expected)
     #expect(Array(metadata[binaryValues: "key-bin"]) == expected)
   }
   }
 
 
+  @Test("Iterate over unpadded base64 encoded binary values for a key")
+  @available(gRPCSwift 2.0, *)
+  func iterateOverUnpaddedBase64BinaryEncodedValuesForKey() {
+    let metadata: Metadata = [
+      "key-bin": "YQ==",
+      "key-bin": "YQ",
+    ]
+
+    let expected: [[UInt8]] = [[UInt8(ascii: "a")], [UInt8(ascii: "a")]]
+    #expect(Array(metadata[binaryValues: "key-bin"]) == expected)
+  }
+
   @Test("Subscripts are case-insensitive")
   @Test("Subscripts are case-insensitive")
   @available(gRPCSwift 2.0, *)
   @available(gRPCSwift 2.0, *)
   func subscriptIsCaseInsensitive() {
   func subscriptIsCaseInsensitive() {