Coverage Report

Created: 2025-06-24 06:59

/src/grpc-swift/Sources/GRPC/Compression/MessageEncoding.swift
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2020, gRPC Authors All rights reserved.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
/// Whether compression should be enabled for the message.
18
public struct Compression: Hashable, Sendable {
19
  @usableFromInline
20
  internal enum _Wrapped: Hashable, Sendable {
21
    case enabled
22
    case disabled
23
    case deferToCallDefault
24
  }
25
26
  @usableFromInline
27
  internal var _wrapped: _Wrapped
28
29
2
  private init(_ wrapped: _Wrapped) {
30
2
    self._wrapped = wrapped
31
2
  }
32
33
  /// Enable compression. Note that this will be ignored if compression has not been enabled or is
34
  /// not supported on the call.
35
  public static let enabled = Compression(.enabled)
36
37
  /// Disable compression.
38
  public static let disabled = Compression(.disabled)
39
40
  /// Defer to the call (the ``CallOptions`` for the client, and the context for the server) to
41
  /// determine whether compression should be used for the message.
42
  public static let deferToCallDefault = Compression(.deferToCallDefault)
43
}
44
45
extension Compression {
46
  @inlinable
47
0
  internal func isEnabled(callDefault: Bool) -> Bool {
48
0
    switch self._wrapped {
49
0
    case .enabled:
50
0
      return callDefault
51
0
    case .disabled:
52
0
      return false
53
0
    case .deferToCallDefault:
54
0
      return callDefault
55
0
    }
56
0
  }
57
}
58
59
/// Whether compression is enabled or disabled for a client.
60
public enum ClientMessageEncoding: Sendable {
61
  /// Compression is enabled with the given configuration.
62
  case enabled(Configuration)
63
  /// Compression is disabled.
64
  case disabled
65
}
66
67
extension ClientMessageEncoding {
68
0
  internal var enabledForRequests: Bool {
69
0
    switch self {
70
0
    case let .enabled(configuration):
71
0
      return configuration.outbound != nil
72
0
    case .disabled:
73
0
      return false
74
0
    }
75
0
  }
76
}
77
78
extension ClientMessageEncoding {
79
  public struct Configuration: Sendable {
80
    public init(
81
      forRequests outbound: CompressionAlgorithm?,
82
      acceptableForResponses inbound: [CompressionAlgorithm] = CompressionAlgorithm.all,
83
      decompressionLimit: DecompressionLimit
84
0
    ) {
85
0
      self.outbound = outbound
86
0
      self.inbound = inbound
87
0
      self.decompressionLimit = decompressionLimit
88
0
    }
89
90
    /// The compression algorithm used for outbound messages.
91
    public var outbound: CompressionAlgorithm?
92
93
    /// The set of compression algorithms advertised to the remote peer that they may use.
94
    public var inbound: [CompressionAlgorithm]
95
96
    /// The decompression limit acceptable for responses. RPCs which receive a message whose
97
    /// decompressed size exceeds the limit will be cancelled.
98
    public var decompressionLimit: DecompressionLimit
99
100
    /// Accept all supported compression on responses, do not compress requests.
101
    public static func responsesOnly(
102
      acceptable: [CompressionAlgorithm] = CompressionAlgorithm.all,
103
      decompressionLimit: DecompressionLimit
104
0
    ) -> Configuration {
105
0
      return Configuration(
106
0
        forRequests: .identity,
107
0
        acceptableForResponses: acceptable,
108
0
        decompressionLimit: decompressionLimit
109
0
      )
110
0
    }
111
112
0
    internal var acceptEncodingHeader: String {
113
0
      return self.inbound.map { $0.name }.joined(separator: ",")
114
0
    }
115
  }
116
}
117
118
/// Whether compression is enabled or disabled on the server.
119
public enum ServerMessageEncoding {
120
  /// Compression is supported with this configuration.
121
  case enabled(Configuration)
122
  /// Compression is not enabled. However, 'identity' compression is still supported.
123
  case disabled
124
125
  @usableFromInline
126
4.55M
  internal var isEnabled: Bool {
127
4.55M
    switch self {
128
4.55M
    case .enabled:
129
0
      return true
130
4.55M
    case .disabled:
131
4.55M
      return false
132
4.55M
    }
133
4.55M
  }
134
}
135
136
extension ServerMessageEncoding {
137
  public struct Configuration {
138
    /// The set of compression algorithms advertised that we will accept from clients for requests.
139
    /// Note that clients may send us messages compressed with algorithms not included in this list;
140
    /// if we support it then we still accept the message.
141
    ///
142
    /// All cases of `CompressionAlgorithm` are supported.
143
    public var enabledAlgorithms: [CompressionAlgorithm]
144
145
    /// The decompression limit acceptable for requests. RPCs which receive a message whose
146
    /// decompressed size exceeds the limit will be cancelled.
147
    public var decompressionLimit: DecompressionLimit
148
149
    /// Create a configuration for server message encoding.
150
    ///
151
    /// - Parameters:
152
    ///   - enabledAlgorithms: The list of algorithms which are enabled.
153
    ///   - decompressionLimit: Decompression limit acceptable for requests.
154
    public init(
155
      enabledAlgorithms: [CompressionAlgorithm] = CompressionAlgorithm.all,
156
      decompressionLimit: DecompressionLimit
157
0
    ) {
158
0
      self.enabledAlgorithms = enabledAlgorithms
159
0
      self.decompressionLimit = decompressionLimit
160
0
    }
161
  }
162
}