From e10694b044d972c70f3fb7ab10576493b1c0e573 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Fri, 2 Feb 2024 15:17:44 +0000 Subject: [PATCH 1/6] Add service and method config Motivation: When resoling addresses, gRPC clients can discover configuration to use published by service maintainers. This is in the form of 'service config' and typically encoded as JSON. However the structure of the config is a translation of the service config protobuf message using the standard proto to JSON mappings. This change expands on the existing `MethodConfiguration` to allow it to be decoded from JSON and adds a `ServiceConfiguration` which can also be decoded from JSON. Modifications: - Add additional properties to `MethodConfiguration` and make it `Codabale` - Add `ServiceConfiguration` and make it `Codabale` - Add a `RuntimeError` - Add the `service_config.proto` message and its dependencies and generate these messages into the test module. Result: Service config and method config are more fully featured --- .../Configuration/MethodConfiguration.swift | 676 ++++++++++++++++++ .../Configuration/ServiceConfiguration.swift | 278 +++++++ Sources/GRPCCore/GRPCClient.swift | 2 +- Sources/GRPCCore/MethodConfiguration.swift | 290 -------- Sources/GRPCCore/RuntimeError.swift | 128 ++++ .../ClientRPCExecutorTestHarness.swift | 5 +- .../ClientRPCExecutorTests+Hedging.swift | 2 +- .../ClientRPCExecutorTests+Retries.swift | 6 +- .../MethodConfigurationCodingTests.swift | 424 +++++++++++ .../MethodConfigurationTests.swift | 0 .../ServiceConfigurationCodingTests.swift | 261 +++++++ .../MethodConfigurationsTests.swift | 12 +- .../InProcessClientTransportTests.swift | 6 +- 13 files changed, 1782 insertions(+), 308 deletions(-) create mode 100644 Sources/GRPCCore/Configuration/MethodConfiguration.swift create mode 100644 Sources/GRPCCore/Configuration/ServiceConfiguration.swift delete mode 100644 Sources/GRPCCore/MethodConfiguration.swift create mode 100644 Sources/GRPCCore/RuntimeError.swift create mode 100644 Tests/GRPCCoreTests/Configuration/MethodConfigurationCodingTests.swift rename Tests/GRPCCoreTests/{ => Configuration}/MethodConfigurationTests.swift (100%) create mode 100644 Tests/GRPCCoreTests/Configuration/ServiceConfigurationCodingTests.swift diff --git a/Sources/GRPCCore/Configuration/MethodConfiguration.swift b/Sources/GRPCCore/Configuration/MethodConfiguration.swift new file mode 100644 index 000000000..fdf9d1f5f --- /dev/null +++ b/Sources/GRPCCore/Configuration/MethodConfiguration.swift @@ -0,0 +1,676 @@ +/* + * Copyright 2023, gRPC Authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// Configuration values for executing an RPC. +/// +/// See also: https://github.com/grpc/grpc-proto/blob/master/grpc/service_config/service_config.proto +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +public struct MethodConfiguration: Hashable, Sendable { + public struct Name: Sendable, Hashable { + /// The name of the service, including the namespace. + /// + /// If the service is empty then `method` must also be empty and the configuration specifies + /// defaults for all methods. + /// + /// - Precondition: If `service` is empty then `method` must also be empty. + public var service: String { + didSet { try! self.validate() } + } + + /// The name of the method. + /// + /// If the method is empty then the configuration will be the default for all methods in the + /// specified service. + public var method: String + + /// Create a new name. + /// + /// If the service is empty then `method` must also be empty and the configuration specifies + /// defaults for all methods. If only `method` is empty then the configuration applies to + /// all methods in the `service`. + /// + /// - Parameters: + /// - service: The name of the service, including the namespace. + /// - method: The name of the method. + public init(service: String, method: String = "") { + self.service = service + self.method = method + try! self.validate() + } + + private func validate() throws { + if self.service.isEmpty && !self.method.isEmpty { + throw RuntimeError( + code: .invalidArgument, + message: "'method' must be empty if 'service' is empty." + ) + } + } + } + + /// The names of methods which this configuration applies to. + public var names: [Name] + + /// The default timeout for the RPC. + /// + /// If no reply is received in the specified amount of time the request is aborted + /// with an ``RPCError`` with code ``RPCError/Code/deadlineExceeded``. + /// + /// The actual deadline used will be the minimum of the value specified here + /// and the value set by the application by the client API. If either one isn't set + /// then the other value is used. If neither is set then the request has no deadline. + /// + /// The timeout applies to the overall execution of an RPC. If, for example, a retry + /// policy is set then the timeout begins when the first attempt is started and _isn't_ reset + /// when subsequent attempts start. + public var timeout: Duration? + + /// The maximum allowed payload size in bytes for an individual message. + /// + /// If a client attempts to send an object larger than this value, it will not be sent and the + /// client will see a error. Note that 0 is a valid value, meaning that the request message + /// must be empty. + public var maxRequestMessageBytes: Int? + + /// The maximum allowed payload size in bytes for an individual response message. + /// + /// If a server attempts to send an object larger than this value, it will not + /// be sent, and an error will be sent to the client instead. Note that 0 is a valid value, + /// meaning that the response message must be empty. + public var maxResponseMessageBytes: Int? + + /// The policy determining how many times, and when, the RPC is executed. + /// + /// There are two policy types: + /// 1. Retry + /// 2. Hedging + /// + /// The retry policy allows an RPC to be retried a limited number of times if the RPC + /// fails with one of the configured set of status codes. RPCs are only retried if they + /// fail immediately, that is, the first response part received from the server is a + /// status code. + /// + /// The hedging policy allows an RPC to be executed multiple times concurrently. Typically + /// each execution will be staggered by some delay. The first successful response will be + /// reported to the client. Hedging is only suitable for idempotent RPCs. + public var executionPolicy: ExecutionPolicy? + + /// Create an execution configuration. + /// + /// - Parameters: + /// - names: The names of methods this configuration applies to. + /// - timeout: The default timeout for the RPC. + /// - maxRequestMessageBytes: The maximum allowed size of a request message in bytes. + /// - maxResponseMessageBytes: The maximum allowed size of a response message in bytes. + /// - executionPolicy: The execution policy to use for the RPC. + public init( + names: [Name], + timeout: Duration? = nil, + maxRequestMessageBytes: Int? = nil, + maxResponseMessageBytes: Int? = nil, + executionPolicy: ExecutionPolicy? = nil + ) { + self.names = names + self.timeout = timeout + self.maxRequestMessageBytes = maxRequestMessageBytes + self.maxResponseMessageBytes = maxResponseMessageBytes + self.executionPolicy = executionPolicy + } +} + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +extension MethodConfiguration { + /// The execution policy for an RPC. + public enum ExecutionPolicy: Hashable, Sendable { + /// Policy for retrying an RPC. + /// + /// See ``RetryPolicy`` for more details. + case retry(RetryPolicy) + + /// Policy for hedging an RPC. + /// + /// See ``HedgingPolicy`` for more details. + case hedge(HedgingPolicy) + } +} + +/// Policy for retrying an RPC. +/// +/// gRPC retries RPCs when the first response from the server is a status code which matches +/// one of the configured retryable status codes. If the server begins processing the RPC and +/// first responds with metadata and later responds with a retryable status code then the RPC +/// won't be retried. +/// +/// Execution attempts are limited by ``maximumAttempts`` which includes the original attempt. The +/// maximum number of attempts is limited to five. +/// +/// Subsequent attempts are executed after some delay. The first _retry_, or second attempt, will +/// be started after a randomly chosen delay between zero and ``initialBackoff``. More generally, +/// the nth retry will happen after a randomly chosen delay between zero +/// and `min(initialBackoff * backoffMultiplier^(n-1), maximumBackoff)`. +/// +/// For more information see [gRFC A6 Client +/// Retries](https://github.com/grpc/proposal/blob/master/A6-client-retries.md). +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +public struct RetryPolicy: Hashable, Sendable { + /// The maximum number of RPC attempts, including the original attempt. + /// + /// Must be greater than one, values greater than five are treated as five. + public var maximumAttempts: Int { + didSet { self.maximumAttempts = try! validateMaxAttempts(self.maximumAttempts) } + } + + /// The initial backoff duration. + /// + /// The initial retry will occur after a random amount of time up to this value. + /// + /// - Precondition: Must be greater than zero. + public var initialBackoff: Duration { + willSet { try! Self.validateInitialBackoff(newValue) } + } + + /// The maximum amount of time to backoff for. + /// + /// - Precondition: Must be greater than zero. + public var maximumBackoff: Duration { + willSet { try! Self.validateMaxBackoff(newValue) } + } + + /// The multiplier to apply to backoff. + /// + /// - Precondition: Must be greater than zero. + public var backoffMultiplier: Double { + willSet { try! Self.validateBackoffMultiplier(newValue) } + } + + /// The set of status codes which may be retried. + /// + /// - Precondition: Must not be empty. + public var retryableStatusCodes: Set { + willSet { try! Self.validateRetryableStatusCodes(newValue) } + } + + /// Create a new retry policy. + /// + /// - Parameters: + /// - maximumAttempts: The maximum number of attempts allowed for the RPC. + /// - initialBackoff: The initial backoff period for the first retry attempt. Must be + /// greater than zero. + /// - maximumBackoff: The maximum period of time to wait between attempts. Must be greater than + /// zero. + /// - backoffMultiplier: The exponential backoff multiplier. Must be greater than zero. + /// - retryableStatusCodes: The set of status codes which may be retried. Must not be empty. + /// - Precondition: `maximumAttempts`, `initialBackoff`, `maximumBackoff` and `backoffMultiplier` + /// must be greater than zero. + /// - Precondition: `retryableStatusCodes` must not be empty. + public init( + maximumAttempts: Int, + initialBackoff: Duration, + maximumBackoff: Duration, + backoffMultiplier: Double, + retryableStatusCodes: Set + ) { + self.maximumAttempts = try! validateMaxAttempts(maximumAttempts) + + try! Self.validateInitialBackoff(initialBackoff) + self.initialBackoff = initialBackoff + + try! Self.validateMaxBackoff(maximumBackoff) + self.maximumBackoff = maximumBackoff + + try! Self.validateBackoffMultiplier(backoffMultiplier) + self.backoffMultiplier = backoffMultiplier + + try! Self.validateRetryableStatusCodes(retryableStatusCodes) + self.retryableStatusCodes = retryableStatusCodes + } + + private static func validateInitialBackoff(_ value: Duration) throws { + if value <= .zero { + throw RuntimeError( + code: .invalidArgument, + message: "initialBackoff must be greater than zero" + ) + } + } + + private static func validateMaxBackoff(_ value: Duration) throws { + if value <= .zero { + throw RuntimeError( + code: .invalidArgument, + message: "maximumBackoff must be greater than zero" + ) + } + } + + private static func validateBackoffMultiplier(_ value: Double) throws { + if value <= 0 { + throw RuntimeError( + code: .invalidArgument, + message: "backoffMultiplier must be greater than zero" + ) + } + } + + private static func validateRetryableStatusCodes(_ value: Set) throws { + if value.isEmpty { + throw RuntimeError(code: .invalidArgument, message: "retryableStatusCodes mustn't be empty") + } + } +} + +/// Policy for hedging an RPC. +/// +/// Hedged RPCs may execute more than once on a server so only idempotent methods should +/// be hedged. +/// +/// gRPC executes the RPC at most ``maximumAttempts`` times, staggering each attempt +/// by ``hedgingDelay``. +/// +/// For more information see [gRFC A6 Client +/// Retries](https://github.com/grpc/proposal/blob/master/A6-client-retries.md). +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +public struct HedgingPolicy: Hashable, Sendable { + /// The maximum number of RPC attempts, including the original attempt. + /// + /// Values greater than five are treated as five. + /// + /// - Precondition: Must be greater than one. + public var maximumAttempts: Int { + didSet { self.maximumAttempts = try! validateMaxAttempts(self.maximumAttempts) } + } + + /// The first RPC will be sent immediately, but each subsequent RPC will be sent at intervals + /// of `hedgingDelay`. Set this to zero to immediately send all RPCs. + public var hedgingDelay: Duration { + willSet { try! Self.validateHedgingDelay(newValue) } + } + + /// The set of status codes which indicate other hedged RPCs may still succeed. + /// + /// If a non-fatal status code is returned by the server, hedged RPCs will continue. + /// Otherwise, outstanding requests will be cancelled and the error returned to the + /// application layer. + public var nonFatalStatusCodes: Set + + /// Create a new hedging policy. + /// + /// - Parameters: + /// - maximumAttempts: The maximum number of attempts allowed for the RPC. + /// - hedgingDelay: The delay between each hedged RPC. + /// - nonFatalStatusCodes: The set of status codes which indicated other hedged RPCs may still + /// succeed. + /// - Precondition: `maximumAttempts` must be greater than zero. + public init( + maximumAttempts: Int, + hedgingDelay: Duration, + nonFatalStatusCodes: Set + ) { + self.maximumAttempts = try! validateMaxAttempts(maximumAttempts) + + try! Self.validateHedgingDelay(hedgingDelay) + self.hedgingDelay = hedgingDelay + self.nonFatalStatusCodes = nonFatalStatusCodes + } + + private static func validateHedgingDelay(_ value: Duration) throws { + if value < .zero { + throw RuntimeError( + code: .invalidArgument, + message: "hedgingDelay must be greater than or equal to zero" + ) + } + } +} + +private func validateMaxAttempts(_ value: Int) throws -> Int { + guard value > 0 else { + throw RuntimeError( + code: .invalidArgument, + message: "max_attempts must be greater than zero (was \(value))" + ) + } + + return min(value, 5) +} + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +extension Duration { + fileprivate init(googleProtobufDuration duration: String) throws { + guard duration.utf8.last == UInt8(ascii: "s"), + let fractionalSeconds = Double(duration.dropLast()) + else { + throw RuntimeError(code: .invalidArgument, message: "Invalid google.protobuf.duration") + } + + let seconds = fractionalSeconds.rounded(.down) + let attoseconds = (fractionalSeconds - seconds) / 1e18 + + self.init(secondsComponent: Int64(seconds), attosecondsComponent: Int64(attoseconds)) + } +} + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +extension MethodConfiguration: Codable { + private enum CodingKeys: String, CodingKey { + case name + case timeout + case maxRequestMessageBytes + case maxResponseMessageBytes + case retryPolicy + case hedgingPolicy + } + + public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.names = try container.decode([Name].self, forKey: .name) + + let timeout = try container.decodeIfPresent(GoogleProtobufDuration.self, forKey: .timeout) + self.timeout = timeout?.duration + + let maxRequestSize = try container.decodeIfPresent(Int.self, forKey: .maxRequestMessageBytes) + self.maxRequestMessageBytes = maxRequestSize + + let maxResponseSize = try container.decodeIfPresent(Int.self, forKey: .maxResponseMessageBytes) + self.maxResponseMessageBytes = maxResponseSize + + if let policy = try container.decodeIfPresent(HedgingPolicy.self, forKey: .hedgingPolicy) { + self.executionPolicy = .hedge(policy) + } else if let policy = try container.decodeIfPresent(RetryPolicy.self, forKey: .retryPolicy) { + self.executionPolicy = .retry(policy) + } else { + self.executionPolicy = nil + } + } + + public func encode(to encoder: any Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(self.names, forKey: .name) + try container.encodeIfPresent( + self.timeout.map { GoogleProtobufDuration(duration: $0) }, + forKey: .timeout + ) + try container.encodeIfPresent(self.maxRequestMessageBytes, forKey: .maxRequestMessageBytes) + try container.encodeIfPresent(self.maxResponseMessageBytes, forKey: .maxResponseMessageBytes) + + switch self.executionPolicy { + case .retry(let policy): + try container.encode(policy, forKey: .retryPolicy) + case .hedge(let policy): + try container.encode(policy, forKey: .hedgingPolicy) + case .none: + () + } + } +} + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +extension MethodConfiguration.Name: Codable { + private enum CodingKeys: String, CodingKey { + case service + case method + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + let service = try container.decodeIfPresent(String.self, forKey: .service) + self.service = service ?? "" + + let method = try container.decodeIfPresent(String.self, forKey: .method) + self.method = method ?? "" + + try self.validate() + } + + public func encode(to encoder: any Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(self.method, forKey: .method) + try container.encode(self.service, forKey: .service) + } +} + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +extension RetryPolicy: Codable { + private enum CodingKeys: String, CodingKey { + case maxAttempts + case initialBackoff + case maxBackoff + case backoffMultiplier + case retryableStatusCodes + } + + public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + let maxAttempts = try container.decode(Int.self, forKey: .maxAttempts) + self.maximumAttempts = try validateMaxAttempts(maxAttempts) + + let initialBackoff = try container.decode(String.self, forKey: .initialBackoff) + self.initialBackoff = try Duration(googleProtobufDuration: initialBackoff) + try Self.validateInitialBackoff(self.initialBackoff) + + let maxBackoff = try container.decode(String.self, forKey: .maxBackoff) + self.maximumBackoff = try Duration(googleProtobufDuration: maxBackoff) + try Self.validateMaxBackoff(self.maximumBackoff) + + self.backoffMultiplier = try container.decode(Double.self, forKey: .backoffMultiplier) + try Self.validateBackoffMultiplier(self.backoffMultiplier) + + let codes = try container.decode([GoogleRPCCode].self, forKey: .retryableStatusCodes) + self.retryableStatusCodes = Set(codes.map { $0.code }) + try Self.validateRetryableStatusCodes(self.retryableStatusCodes) + } + + public func encode(to encoder: any Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(self.maximumAttempts, forKey: .maxAttempts) + try container.encode( + GoogleProtobufDuration(duration: self.initialBackoff), + forKey: .initialBackoff + ) + try container.encode(GoogleProtobufDuration(duration: self.maximumBackoff), forKey: .maxBackoff) + try container.encode(self.backoffMultiplier, forKey: .backoffMultiplier) + try container.encode( + self.retryableStatusCodes.map { $0.googleRPCCode }, + forKey: .retryableStatusCodes + ) + } +} + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +extension HedgingPolicy: Codable { + private enum CodingKeys: String, CodingKey { + case maxAttempts + case hedgingDelay + case nonFatalStatusCodes + } + + public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + let maxAttempts = try container.decode(Int.self, forKey: .maxAttempts) + self.maximumAttempts = try validateMaxAttempts(maxAttempts) + + let delay = try container.decode(String.self, forKey: .hedgingDelay) + self.hedgingDelay = try Duration(googleProtobufDuration: delay) + + let statusCodes = try container.decode([GoogleRPCCode].self, forKey: .nonFatalStatusCodes) + self.nonFatalStatusCodes = Set(statusCodes.map { $0.code }) + } + + public func encode(to encoder: any Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(self.maximumAttempts, forKey: .maxAttempts) + try container.encode(GoogleProtobufDuration(duration: self.hedgingDelay), forKey: .hedgingDelay) + try container.encode( + self.nonFatalStatusCodes.map { $0.googleRPCCode }, + forKey: .nonFatalStatusCodes + ) + } +} + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +struct GoogleProtobufDuration: Codable { + var duration: Duration + + init(duration: Duration) { + self.duration = duration + } + + init(from decoder: any Decoder) throws { + let container = try decoder.singleValueContainer() + let duration = try container.decode(String.self) + + guard duration.utf8.last == UInt8(ascii: "s"), + let fractionalSeconds = Double(duration.dropLast()) + else { + throw RuntimeError(code: .invalidArgument, message: "Invalid google.protobuf.duration") + } + + let seconds = fractionalSeconds.rounded(.down) + let attoseconds = (fractionalSeconds - seconds) * 1e18 + + self.duration = Duration( + secondsComponent: Int64(seconds), + attosecondsComponent: Int64(attoseconds) + ) + } + + func encode(to encoder: any Encoder) throws { + var container = encoder.singleValueContainer() + + var seconds = Double(self.duration.components.seconds) + seconds += Double(self.duration.components.attoseconds) / 1e18 + + let durationString = "\(seconds)s" + try container.encode(durationString) + } +} + +struct GoogleRPCCode: Codable { + var code: Status.Code + + init(code: Status.Code) { + self.code = code + } + + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let code: Status.Code? + + if let caseName = try? container.decode(String.self) { + code = Status.Code(googleRPCCode: caseName) + } else if let rawValue = try? container.decode(Int.self) { + code = Status.Code(rawValue: rawValue) + } else { + code = nil + } + + if let code = code { + self.code = code + } else { + throw RuntimeError(code: .invalidArgument, message: "Invalid google.rpc.code") + } + } + + func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(self.code.googleRPCCode) + } +} + +extension Status.Code { + fileprivate init?(googleRPCCode code: String) { + switch code { + case "OK": + self = .ok + case "CANCELLED": + self = .cancelled + case "UNKNOWN": + self = .unknown + case "INVALID_ARGUMENT": + self = .invalidArgument + case "DEADLINE_EXCEEDED": + self = .deadlineExceeded + case "NOT_FOUND": + self = .notFound + case "ALREADY_EXISTS": + self = .alreadyExists + case "PERMISSION_DENIED": + self = .permissionDenied + case "RESOURCE_EXHAUSTED": + self = .resourceExhausted + case "FAILED_PRECONDITION": + self = .failedPrecondition + case "ABORTED": + self = .aborted + case "OUT_OF_RANGE": + self = .outOfRange + case "UNIMPLEMENTED": + self = .unimplemented + case "INTERNAL": + self = .internalError + case "UNAVAILABLE": + self = .unavailable + case "DATA_LOSS": + self = .dataLoss + case "UNAUTHENTICATED": + self = .unauthenticated + default: + return nil + } + } + + fileprivate var googleRPCCode: String { + switch self.wrapped { + case .ok: + return "OK" + case .cancelled: + return "CANCELLED" + case .unknown: + return "UNKNOWN" + case .invalidArgument: + return "INVALID_ARGUMENT" + case .deadlineExceeded: + return "DEADLINE_EXCEEDED" + case .notFound: + return "NOT_FOUND" + case .alreadyExists: + return "ALREADY_EXISTS" + case .permissionDenied: + return "PERMISSION_DENIED" + case .resourceExhausted: + return "RESOURCE_EXHAUSTED" + case .failedPrecondition: + return "FAILED_PRECONDITION" + case .aborted: + return "ABORTED" + case .outOfRange: + return "OUT_OF_RANGE" + case .unimplemented: + return "UNIMPLEMENTED" + case .internalError: + return "INTERNAL" + case .unavailable: + return "UNAVAILABLE" + case .dataLoss: + return "DATA_LOSS" + case .unauthenticated: + return "UNAUTHENTICATED" + } + } +} diff --git a/Sources/GRPCCore/Configuration/ServiceConfiguration.swift b/Sources/GRPCCore/Configuration/ServiceConfiguration.swift new file mode 100644 index 000000000..17d178623 --- /dev/null +++ b/Sources/GRPCCore/Configuration/ServiceConfiguration.swift @@ -0,0 +1,278 @@ +/* + * Copyright 2024, gRPC Authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// Service configuration values. +/// +/// See also: https://github.com/grpc/grpc-proto/blob/master/grpc/service_config/service_config.proto +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +public struct ServiceConfiguration: Hashable, Sendable { + /// Per-method configuration. + public var methodConfiguration: [MethodConfiguration] + + /// Load balancing policies. + /// + /// The client iterates through the list in order and picks the first configuration it supports. + /// If no policies are supported then the configuration is considered to be invalid. + public var loadBalancingConfiguration: [LoadBalancingConfiguration] + + /// The policy for throttling retries. + /// + /// If a ``RetryThrottlingPolicy`` is provided, gRPC will automatically throttle retry attempts + /// and hedged RPCs when the client's ratio of failures to successes exceeds a threshold. + /// + /// For each server name, the gRPC client will maintain a `token_count` which is initially set + /// to ``maxTokens``. Every outgoing RPC (regardless of service or method invoked) will change + /// `token_count` as follows: + /// + /// - Every failed RPC will decrement the `token_count` by 1. + /// - Every successful RPC will increment the `token_count` by ``tokenRatio``. + /// + /// If `token_count` is less than or equal to `max_tokens / 2`, then RPCs will not be retried + /// and hedged RPCs will not be sent. + public var retryThrottlingPolicy: RetryThrottlingPolicy? + + /// Creates a new ``ServiceConfiguration``. + /// + /// - Parameters: + /// - methodConfiguration: Per-method configuration. + /// - loadBalancingConfiguration: Load balancing policies. Clients use the the first supported + /// policy when iterating the list in order. + /// - retryThrottlingPolicy: Policy for throttling retries. + public init( + methodConfiguration: [MethodConfiguration] = [], + loadBalancingConfiguration: [LoadBalancingConfiguration] = [], + retryThrottlingPolicy: RetryThrottlingPolicy? = nil + ) { + self.methodConfiguration = methodConfiguration + self.loadBalancingConfiguration = loadBalancingConfiguration + self.retryThrottlingPolicy = retryThrottlingPolicy + } +} + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +extension ServiceConfiguration: Codable { + private enum CodingKeys: String, CodingKey { + case methodConfig + case loadBalancingConfig + case retryThrottling + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + let methodConfiguration = try container.decodeIfPresent( + [MethodConfiguration].self, + forKey: .methodConfig + ) + self.methodConfiguration = methodConfiguration ?? [] + + let loadBalancingConfiguration = try container.decodeIfPresent( + [LoadBalancingConfiguration].self, + forKey: .loadBalancingConfig + ) + self.loadBalancingConfiguration = loadBalancingConfiguration ?? [] + + self.retryThrottlingPolicy = try container.decodeIfPresent( + RetryThrottlingPolicy.self, + forKey: .retryThrottling + ) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(self.methodConfiguration, forKey: .methodConfig) + try container.encode(self.loadBalancingConfiguration, forKey: .loadBalancingConfig) + try container.encodeIfPresent(self.retryThrottlingPolicy, forKey: .retryThrottling) + } +} + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +extension ServiceConfiguration { + /// Configuration used by clients for load-balancing. + public struct LoadBalancingConfiguration: Hashable, Sendable { + private enum Value: Hashable, Sendable { + case pickFirst(PickFirst) + case roundRobin(RoundRobin) + } + + private var value: Value? + private init(_ value: Value) { + self.value = value + } + + /// Creates a pick-first load balancing policy. + /// + /// - Parameter shuffleAddressList: Whether resolved addresses should be shuffled before + /// attempting to connect to them. + public static func pickFirst(shuffleAddressList: Bool) -> Self { + Self(.pickFirst(PickFirst(shuffleAddressList: shuffleAddressList))) + } + + /// Creates a pick-first load balancing policy. + /// + /// - Parameter pickFirst: The pick-first load balancing policy. + public static func pickFirst(_ pickFirst: PickFirst) -> Self { + Self(.pickFirst(pickFirst)) + } + + /// Creates a round-robin load balancing policy. + public static var roundRobin: Self { + Self(.roundRobin(RoundRobin())) + } + + /// The pick-first policy, if configured. + public var pickFirst: PickFirst? { + get { + switch self.value { + case .pickFirst(let value): + return value + default: + return nil + } + } + set { + self.value = newValue.map { .pickFirst($0) } + } + } + + /// The round-robin policy, if configured. + public var roundRobin: RoundRobin? { + get { + switch self.value { + case .roundRobin(let value): + return value + default: + return nil + } + } + set { + self.value = newValue.map { .roundRobin($0) } + } + } + } +} + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +extension ServiceConfiguration.LoadBalancingConfiguration { + /// Configuration for the pick-first load balancing policy. + public struct PickFirst: Hashable, Sendable, Codable { + /// Whether the resolved addresses should be shuffled before attempting to connect to them. + public var shuffleAddressList: Bool + + /// Creates a new pick-first load balancing policy. + /// - Parameter shuffleAddressList: Whether the resolved addresses should be shuffled before + /// attempting to connect to them. + public init(shuffleAddressList: Bool = false) { + self.shuffleAddressList = shuffleAddressList + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let shuffle = try container.decodeIfPresent(Bool.self, forKey: .shuffleAddressList) ?? false + self.shuffleAddressList = shuffle + } + } + + /// Configuration for the round-robin load balancing policy. + public struct RoundRobin: Hashable, Sendable, Codable { + /// Creates a new round-robin load balancing policy. + public init() {} + } +} + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +extension ServiceConfiguration.LoadBalancingConfiguration: Codable { + private enum CodingKeys: String, CodingKey { + case roundRobin = "round_robin" + case pickFirst = "pick_first" + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + if let value = try container.decodeIfPresent(RoundRobin.self, forKey: .roundRobin) { + self.value = .roundRobin(value) + } else if let value = try container.decodeIfPresent(PickFirst.self, forKey: .pickFirst) { + self.value = .pickFirst(value) + } else { + self.value = nil + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + switch self.value { + case .pickFirst(let value): + try container.encode(value, forKey: .pickFirst) + case .roundRobin(let value): + try container.encode(value, forKey: .roundRobin) + case .none: + () + } + } +} + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +extension ServiceConfiguration { + public struct RetryThrottlingPolicy: Hashable, Sendable, Codable { + /// The initial, and maximum number of tokens. + /// + /// - Precondition: Must be greater than zero. + public var maxTokens: Int + + /// The amount of tokens to add on each successful RPC. + /// + /// Typically this will be some number between 0 and 1, e.g., 0.1. Up to three decimal places + /// are supported. + /// + /// - Precondition: Must be greater than zero. + public var tokenRatio: Double + + /// Creates a new retry throttling policy. + /// + /// - Parameters: + /// - maxTokens: The initial, and maximum number of tokens. Must be greater than zero. + /// - tokenRatio: The amount of tokens to add on each successful RPc. Must be greater + /// than zero. + public init(maxTokens: Int, tokenRatio: Double) throws { + self.maxTokens = maxTokens + self.tokenRatio = tokenRatio + + try self.validateMaxTokens() + try self.validateTokenRatio() + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.maxTokens = try container.decode(Int.self, forKey: .maxTokens) + self.tokenRatio = try container.decode(Double.self, forKey: .tokenRatio) + + try self.validateMaxTokens() + try self.validateTokenRatio() + } + + private func validateMaxTokens() throws { + if self.maxTokens <= 0 { + throw RuntimeError(code: .invalidArgument, message: "maxTokens must be greater than zero") + } + } + + private func validateTokenRatio() throws { + if self.tokenRatio <= 0 { + throw RuntimeError(code: .invalidArgument, message: "tokenRatio must be greater than zero") + } + } + } +} diff --git a/Sources/GRPCCore/GRPCClient.swift b/Sources/GRPCCore/GRPCClient.swift index 22f054f59..d2434205e 100644 --- a/Sources/GRPCCore/GRPCClient.swift +++ b/Sources/GRPCCore/GRPCClient.swift @@ -393,7 +393,7 @@ public struct GRPCClient: Sendable { } // No configuration found, return the "vanilla" configuration. - return MethodConfiguration(executionPolicy: nil, timeout: nil) + return MethodConfiguration(names: [], timeout: nil, executionPolicy: nil) } } diff --git a/Sources/GRPCCore/MethodConfiguration.swift b/Sources/GRPCCore/MethodConfiguration.swift deleted file mode 100644 index 14d2f717f..000000000 --- a/Sources/GRPCCore/MethodConfiguration.swift +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright 2023, gRPC Authors All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/// Configuration values for executing an RPC. -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) -public struct MethodConfiguration: Hashable, Sendable { - /// The default timeout for the RPC. - /// - /// If no reply is received in the specified amount of time the request is aborted - /// with an ``RPCError`` with code ``RPCError/Code/deadlineExceeded``. - /// - /// The actual deadline used will be the minimum of the value specified here - /// and the value set by the application by the client API. If either one isn't set - /// then the other value is used. If neither is set then the request has no deadline. - /// - /// The timeout applies to the overall execution of an RPC. If, for example, a retry - /// policy is set then the timeout begins when the first attempt is started and _isn't_ reset - /// when subsequent attempts start. - public var timeout: Duration? - - /// The policy determining how many times, and when, the RPC is executed. - /// - /// There are two policy types: - /// 1. Retry - /// 2. Hedging - /// - /// The retry policy allows an RPC to be retried a limited number of times if the RPC - /// fails with one of the configured set of status codes. RPCs are only retried if they - /// fail immediately, that is, the first response part received from the server is a - /// status code. - /// - /// The hedging policy allows an RPC to be executed multiple times concurrently. Typically - /// each execution will be staggered by some delay. The first successful response will be - /// reported to the client. Hedging is only suitable for idempotent RPCs. - public var executionPolicy: ExecutionPolicy? - - /// Create an execution configuration. - /// - /// - Parameters: - /// - executionPolicy: The execution policy to use for the RPC. - /// - timeout: The default timeout for the RPC. - public init( - executionPolicy: ExecutionPolicy?, - timeout: Duration? - ) { - self.executionPolicy = executionPolicy - self.timeout = timeout - } - - /// Create an execution configuration with a retry policy. - /// - /// - Parameters: - /// - retryPolicy: The policy for retrying the RPC. - /// - timeout: The default timeout for the RPC. - public init( - retryPolicy: RetryPolicy, - timeout: Duration? = nil - ) { - self.executionPolicy = .retry(retryPolicy) - self.timeout = timeout - } - - /// Create an execution configuration with a hedging policy. - /// - /// - Parameters: - /// - hedgingPolicy: The policy for hedging the RPC. - /// - timeout: The default timeout for the RPC. - public init( - hedgingPolicy: HedgingPolicy, - timeout: Duration? = nil - ) { - self.executionPolicy = .hedge(hedgingPolicy) - self.timeout = timeout - } -} - -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) -extension MethodConfiguration { - /// The execution policy for an RPC. - public enum ExecutionPolicy: Hashable, Sendable { - /// Policy for retrying an RPC. - /// - /// See ``RetryPolicy`` for more details. - case retry(RetryPolicy) - - /// Policy for hedging an RPC. - /// - /// See ``HedgingPolicy`` for more details. - case hedge(HedgingPolicy) - } -} - -/// Policy for retrying an RPC. -/// -/// gRPC retries RPCs when the first response from the server is a status code which matches -/// one of the configured retryable status codes. If the server begins processing the RPC and -/// first responds with metadata and later responds with a retryable status code then the RPC -/// won't be retried. -/// -/// Execution attempts are limited by ``maximumAttempts`` which includes the original attempt. The -/// maximum number of attempts is limited to five. -/// -/// Subsequent attempts are executed after some delay. The first _retry_, or second attempt, will -/// be started after a randomly chosen delay between zero and ``initialBackoff``. More generally, -/// the nth retry will happen after a randomly chosen delay between zero -/// and `min(initialBackoff * backoffMultiplier^(n-1), maximumBackoff)`. -/// -/// For more information see [gRFC A6 Client -/// Retries](https://github.com/grpc/proposal/blob/master/A6-client-retries.md). -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) -public struct RetryPolicy: Hashable, Sendable { - /// The maximum number of RPC attempts, including the original attempt. - /// - /// Must be greater than one, values greater than five are treated as five. - public var maximumAttempts: Int { - didSet { self.maximumAttempts = validateMaxAttempts(self.maximumAttempts) } - } - - /// The initial backoff duration. - /// - /// The initial retry will occur after a random amount of time up to this value. - /// - /// - Precondition: Must be greater than zero. - public var initialBackoff: Duration { - willSet { Self.validateInitialBackoff(newValue) } - } - - /// The maximum amount of time to backoff for. - /// - /// - Precondition: Must be greater than zero. - public var maximumBackoff: Duration { - willSet { Self.validateMaxBackoff(newValue) } - } - - /// The multiplier to apply to backoff. - /// - /// - Precondition: Must be greater than zero. - public var backoffMultiplier: Double { - willSet { Self.validateBackoffMultiplier(newValue) } - } - - /// The set of status codes which may be retried. - /// - /// - Precondition: Must not be empty. - public var retryableStatusCodes: Set { - willSet { Self.validateRetryableStatusCodes(newValue) } - } - - /// Create a new retry policy. - /// - /// - Parameters: - /// - maximumAttempts: The maximum number of attempts allowed for the RPC. - /// - initialBackoff: The initial backoff period for the first retry attempt. Must be - /// greater than zero. - /// - maximumBackoff: The maximum period of time to wait between attempts. Must be greater than - /// zero. - /// - backoffMultiplier: The exponential backoff multiplier. Must be greater than zero. - /// - retryableStatusCodes: The set of status codes which may be retried. Must not be empty. - /// - Precondition: `maximumAttempts`, `initialBackoff`, `maximumBackoff` and `backoffMultiplier` - /// must be greater than zero. - /// - Precondition: `retryableStatusCodes` must not be empty. - public init( - maximumAttempts: Int, - initialBackoff: Duration, - maximumBackoff: Duration, - backoffMultiplier: Double, - retryableStatusCodes: Set - ) { - self.maximumAttempts = validateMaxAttempts(maximumAttempts) - - Self.validateInitialBackoff(initialBackoff) - self.initialBackoff = initialBackoff - - Self.validateMaxBackoff(maximumBackoff) - self.maximumBackoff = maximumBackoff - - Self.validateBackoffMultiplier(backoffMultiplier) - self.backoffMultiplier = backoffMultiplier - - Self.validateRetryableStatusCodes(retryableStatusCodes) - self.retryableStatusCodes = retryableStatusCodes - } - - private static func validateInitialBackoff(_ value: Duration) { - precondition(value.isGreaterThanZero, "initialBackoff must be greater than zero") - } - - private static func validateMaxBackoff(_ value: Duration) { - precondition(value.isGreaterThanZero, "maximumBackoff must be greater than zero") - } - - private static func validateBackoffMultiplier(_ value: Double) { - precondition(value > 0, "backoffMultiplier must be greater than zero") - } - - private static func validateRetryableStatusCodes(_ value: Set) { - precondition(!value.isEmpty, "retryableStatusCodes mustn't be empty") - } -} - -/// Policy for hedging an RPC. -/// -/// Hedged RPCs may execute more than once on a server so only idempotent methods should -/// be hedged. -/// -/// gRPC executes the RPC at most ``maximumAttempts`` times, staggering each attempt -/// by ``hedgingDelay``. -/// -/// For more information see [gRFC A6 Client -/// Retries](https://github.com/grpc/proposal/blob/master/A6-client-retries.md). -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) -public struct HedgingPolicy: Hashable, Sendable { - /// The maximum number of RPC attempts, including the original attempt. - /// - /// Values greater than five are treated as five. - /// - /// - Precondition: Must be greater than one. - public var maximumAttempts: Int { - didSet { self.maximumAttempts = validateMaxAttempts(self.maximumAttempts) } - } - - /// The first RPC will be sent immediately, but each subsequent RPC will be sent at intervals - /// of `hedgingDelay`. Set this to zero to immediately send all RPCs. - public var hedgingDelay: Duration { - willSet { Self.validateHedgingDelay(newValue) } - } - - /// The set of status codes which indicate other hedged RPCs may still succeed. - /// - /// If a non-fatal status code is returned by the server, hedged RPCs will continue. - /// Otherwise, outstanding requests will be cancelled and the error returned to the - /// application layer. - public var nonFatalStatusCodes: Set - - /// Create a new hedging policy. - /// - /// - Parameters: - /// - maximumAttempts: The maximum number of attempts allowed for the RPC. - /// - hedgingDelay: The delay between each hedged RPC. - /// - nonFatalStatusCodes: The set of status codes which indicated other hedged RPCs may still - /// succeed. - /// - Precondition: `maximumAttempts` must be greater than zero. - public init( - maximumAttempts: Int, - hedgingDelay: Duration, - nonFatalStatusCodes: Set - ) { - self.maximumAttempts = validateMaxAttempts(maximumAttempts) - - Self.validateHedgingDelay(hedgingDelay) - self.hedgingDelay = hedgingDelay - self.nonFatalStatusCodes = nonFatalStatusCodes - } - - private static func validateHedgingDelay(_ value: Duration) { - precondition( - value.isGreaterThanOrEqualToZero, - "hedgingDelay must be greater than or equal to zero" - ) - } -} - -private func validateMaxAttempts(_ value: Int) -> Int { - precondition(value > 0, "maximumAttempts must be greater than zero") - return min(value, 5) -} - -@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) -extension Duration { - fileprivate var isGreaterThanZero: Bool { - self.components.seconds > 0 || self.components.attoseconds > 0 - } - - fileprivate var isGreaterThanOrEqualToZero: Bool { - self.components.seconds >= 0 || self.components.attoseconds >= 0 - } -} diff --git a/Sources/GRPCCore/RuntimeError.swift b/Sources/GRPCCore/RuntimeError.swift new file mode 100644 index 000000000..74b0e7b7a --- /dev/null +++ b/Sources/GRPCCore/RuntimeError.swift @@ -0,0 +1,128 @@ +/* + * Copyright 2024, gRPC Authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// An error thrown at runtime. +/// +/// In contrast to ``RPCError``, the ``RuntimeError`` represents errors which happen at a scope +/// wider than an individual RPC. For example, passing invalid configuration values. +public struct RuntimeError: Error, Hashable, @unchecked Sendable { + private var storage: Storage + + // Ensures the underlying storage is unique. + private mutating func ensureUniqueStorage() { + if !isKnownUniquelyReferenced(&self.storage) { + self.storage = self.storage.copy() + } + } + + /// The code indicating the domain of the error. + public var code: Code { + get { self.storage.code } + set { + self.ensureUniqueStorage() + self.storage.code = newValue + } + } + + /// A message providing more details about the error which may include details specific to this + /// instance of the error. + public var message: String { + get { self.storage.message } + set { + self.ensureUniqueStorage() + self.storage.message = newValue + } + } + + /// The original error which led to this error being thrown. + public var cause: Error? { + get { self.storage.cause } + set { + self.ensureUniqueStorage() + self.storage.cause = newValue + } + } + + /// Creates a new error. + /// + /// - Parameters: + /// - code: The error code. + /// - message: A description of the error. + /// - cause: The original error which led to this error being thrown. + public init(code: Code, message: String, cause: Error? = nil) { + self.storage = Storage(code: code, message: message, cause: cause) + } +} + +extension RuntimeError: CustomStringConvertible { + public var description: String { + if let cause = self.cause { + return "\(self.code): \"\(self.message)\" (cause: \"\(cause)\")" + } else { + return "\(self.code): \"\(self.message)\"" + } + } +} + +extension RuntimeError { + private final class Storage: Hashable { + var code: Code + var message: String + var cause: Error? + + init(code: Code, message: String, cause: Error?) { + self.code = code + self.message = message + self.cause = cause + } + + func copy() -> Storage { + return Storage(code: self.code, message: self.message, cause: self.cause) + } + + func hash(into hasher: inout Hasher) { + hasher.combine(self.code) + hasher.combine(self.message) + } + + static func == (lhs: Storage, rhs: Storage) -> Bool { + return lhs.code == rhs.code && lhs.message == rhs.message + } + } +} + +extension RuntimeError { + public struct Code: Hashable, Sendable { + private enum Value { + case invalidArgument + } + + private var value: Value + private init(_ value: Value) { + self.value = value + } + + public static var invalidArgument: Self { + Self(.invalidArgument) + } + } +} + +extension RuntimeError.Code: CustomStringConvertible { + public var description: String { + String(describing: self.value) + } +} diff --git a/Tests/GRPCCoreTests/Call/Client/Internal/ClientRPCExecutorTestSupport/ClientRPCExecutorTestHarness.swift b/Tests/GRPCCoreTests/Call/Client/Internal/ClientRPCExecutorTestSupport/ClientRPCExecutorTestHarness.swift index 9aacff2d7..fc882b7ba 100644 --- a/Tests/GRPCCoreTests/Call/Client/Internal/ClientRPCExecutorTestSupport/ClientRPCExecutorTestHarness.swift +++ b/Tests/GRPCCoreTests/Call/Client/Internal/ClientRPCExecutorTestSupport/ClientRPCExecutorTestHarness.swift @@ -146,10 +146,7 @@ struct ClientRPCExecutorTestHarness { if let configuration = configuration { executionConfiguration = configuration } else { - executionConfiguration = MethodConfiguration( - executionPolicy: nil, - timeout: nil - ) + executionConfiguration = MethodConfiguration(names: []) } // Execute the request. diff --git a/Tests/GRPCCoreTests/Call/Client/Internal/ClientRPCExecutorTests+Hedging.swift b/Tests/GRPCCoreTests/Call/Client/Internal/ClientRPCExecutorTests+Hedging.swift index 79663bfee..ef780fef4 100644 --- a/Tests/GRPCCoreTests/Call/Client/Internal/ClientRPCExecutorTests+Hedging.swift +++ b/Tests/GRPCCoreTests/Call/Client/Internal/ClientRPCExecutorTests+Hedging.swift @@ -200,6 +200,6 @@ extension MethodConfiguration { nonFatalStatusCodes: nonFatalCodes ) - return Self(hedgingPolicy: policy, timeout: timeout) + return Self(names: [], timeout: timeout, executionPolicy: .hedge(policy)) } } diff --git a/Tests/GRPCCoreTests/Call/Client/Internal/ClientRPCExecutorTests+Retries.swift b/Tests/GRPCCoreTests/Call/Client/Internal/ClientRPCExecutorTests+Retries.swift index e20f48352..e2a529228 100644 --- a/Tests/GRPCCoreTests/Call/Client/Internal/ClientRPCExecutorTests+Retries.swift +++ b/Tests/GRPCCoreTests/Call/Client/Internal/ClientRPCExecutorTests+Retries.swift @@ -236,7 +236,7 @@ extension ClientRPCExecutorTests { request: ClientRequest.Stream { try await $0.write([0]) }, - configuration: .init(retryPolicy: retryPolicy) + configuration: .init(names: [], executionPolicy: .retry(retryPolicy)) ) { response in let end = ContinuousClock.now let duration = end - start @@ -272,7 +272,7 @@ extension ClientRPCExecutorTests { request: ClientRequest.Stream { try await $0.write([0]) }, - configuration: .init(retryPolicy: retryPolicy) + configuration: .init(names: [], executionPolicy: .retry(retryPolicy)) ) { response in switch response.accepted { case .success: @@ -304,6 +304,6 @@ extension MethodConfiguration { retryableStatusCodes: codes ) - return Self(retryPolicy: policy, timeout: timeout) + return Self(names: [], timeout: timeout, executionPolicy: .retry(policy)) } } diff --git a/Tests/GRPCCoreTests/Configuration/MethodConfigurationCodingTests.swift b/Tests/GRPCCoreTests/Configuration/MethodConfigurationCodingTests.swift new file mode 100644 index 000000000..aeeb7e343 --- /dev/null +++ b/Tests/GRPCCoreTests/Configuration/MethodConfigurationCodingTests.swift @@ -0,0 +1,424 @@ +/* + * Copyright 2024, gRPC Authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Foundation +import SwiftProtobuf +import XCTest + +@testable import GRPCCore + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +internal final class MethodConfigurationCodingTests: XCTestCase { + private let encoder = JSONEncoder() + private let decoder = JSONDecoder() + + private func testDecodeThrowsRuntimeError(json: String, as: D.Type) throws { + XCTAssertThrowsError( + ofType: RuntimeError.self, + try self.decoder.decode(D.self, from: Data(json.utf8)) + ) { error in + XCTAssertEqual(error.code, .invalidArgument) + } + } + + func testDecodeMethodConfigName() throws { + let inputs: [(String, MethodConfiguration.Name)] = [ + (#"{"service": "foo.bar", "method": "baz"}"#, .init(service: "foo.bar", method: "baz")), + (#"{"service": "foo.bar"}"#, .init(service: "foo.bar", method: "")), + (#"{}"#, .init(service: "", method: "")), + ] + + for (json, expected) in inputs { + let decoded = try self.decoder.decode(MethodConfiguration.Name.self, from: Data(json.utf8)) + XCTAssertEqual(decoded, expected) + } + } + + func testEncodeDecodeMethodConfigName() throws { + let inputs: [MethodConfiguration.Name] = [ + MethodConfiguration.Name(service: "foo.bar", method: "baz"), + MethodConfiguration.Name(service: "foo.bar", method: ""), + MethodConfiguration.Name(service: "", method: ""), + ] + + // We can't do encode-only tests as the output is non-deterministic (the ordering of + // service/method in the JSON object) + for name in inputs { + let encoded = try self.encoder.encode(name) + let decoded = try self.decoder.decode(MethodConfiguration.Name.self, from: encoded) + XCTAssertEqual(decoded, name) + } + } + + func testDecodeProtobufDuration() throws { + let inputs: [(String, Duration)] = [ + ("1.0s", .seconds(1)), + ("1s", .seconds(1)), + ("1.000000s", .seconds(1)), + ("0s", .zero), + ("100.123s", .milliseconds(100_123)), + ] + + for (input, expected) in inputs { + let json = "\"\(input)\"" + let protoDuration = try self.decoder.decode( + GoogleProtobufDuration.self, + from: Data(json.utf8) + ) + let components = protoDuration.duration.components + + // Conversion is lossy as we go from floating point seconds to integer seconds and + // attoseconds. Allow for millisecond precision. + let divisor: Int64 = 1_000_000_000_000_000 + + XCTAssertEqual(components.seconds, expected.components.seconds) + XCTAssertEqual(components.attoseconds / divisor, expected.components.attoseconds / divisor) + } + } + + func testEncodeProtobufDuration() throws { + let inputs: [(Duration, String)] = [ + (.seconds(1), "\"1.0s\""), + (.zero, "\"0.0s\""), + (.milliseconds(100_123), "\"100.123s\""), + ] + + for (input, expected) in inputs { + let duration = GoogleProtobufDuration(duration: input) + let encoded = try self.encoder.encode(duration) + let json = String(decoding: encoded, as: UTF8.self) + XCTAssertEqual(json, expected) + } + } + + func testDecodeInvalidProtobufDuration() throws { + for timestamp in ["1", "1ss", "1S", "1.0S"] { + let json = "\"\(timestamp)\"" + try self.testDecodeThrowsRuntimeError(json: json, as: GoogleProtobufDuration.self) + } + } + + func testDecodeRPCCodeFromCaseName() throws { + let inputs: [(String, Status.Code)] = [ + ("OK", .ok), + ("CANCELLED", .cancelled), + ("UNKNOWN", .unknown), + ("INVALID_ARGUMENT", .invalidArgument), + ("DEADLINE_EXCEEDED", .deadlineExceeded), + ("NOT_FOUND", .notFound), + ("ALREADY_EXISTS", .alreadyExists), + ("PERMISSION_DENIED", .permissionDenied), + ("RESOURCE_EXHAUSTED", .resourceExhausted), + ("FAILED_PRECONDITION", .failedPrecondition), + ("ABORTED", .aborted), + ("OUT_OF_RANGE", .outOfRange), + ("UNIMPLEMENTED", .unimplemented), + ("INTERNAL", .internalError), + ("UNAVAILABLE", .unavailable), + ("DATA_LOSS", .dataLoss), + ("UNAUTHENTICATED", .unauthenticated), + ] + + for (name, expected) in inputs { + let json = "\"\(name)\"" + let code = try self.decoder.decode(GoogleRPCCode.self, from: Data(json.utf8)) + XCTAssertEqual(code.code, expected) + } + } + + func testDecodeRPCCodeFromRawValue() throws { + let inputs: [(Int, Status.Code)] = [ + (0, .ok), + (1, .cancelled), + (2, .unknown), + (3, .invalidArgument), + (4, .deadlineExceeded), + (5, .notFound), + (6, .alreadyExists), + (7, .permissionDenied), + (8, .resourceExhausted), + (9, .failedPrecondition), + (10, .aborted), + (11, .outOfRange), + (12, .unimplemented), + (13, .internalError), + (14, .unavailable), + (15, .dataLoss), + (16, .unauthenticated), + ] + + for (rawValue, expected) in inputs { + let json = "\(rawValue)" + let code = try self.decoder.decode(GoogleRPCCode.self, from: Data(json.utf8)) + XCTAssertEqual(code.code, expected) + } + } + + func testEncodeDecodeRPCCode() throws { + let codes: [Status.Code] = [ + .ok, + .cancelled, + .unknown, + .invalidArgument, + .deadlineExceeded, + .notFound, + .alreadyExists, + .permissionDenied, + .resourceExhausted, + .failedPrecondition, + .aborted, + .outOfRange, + .unimplemented, + .internalError, + .unavailable, + .dataLoss, + .unauthenticated, + ] + + for code in codes { + let encoded = try self.encoder.encode(GoogleRPCCode(code: code)) + let decoded = try self.decoder.decode(GoogleRPCCode.self, from: encoded) + XCTAssertEqual(decoded.code, code) + } + } + + func testDecodeRetryPolicy() throws { + let json = """ + { + "maxAttempts": 1, + "initialBackoff": "1s", + "maxBackoff": "3s", + "backoffMultiplier": 1.6, + "retryableStatusCodes": ["ABORTED"] + } + """ + + let expected = RetryPolicy( + maximumAttempts: 1, + initialBackoff: .seconds(1), + maximumBackoff: .seconds(3), + backoffMultiplier: 1.6, + retryableStatusCodes: [.aborted] + ) + + let decoded = try self.decoder.decode(RetryPolicy.self, from: Data(json.utf8)) + XCTAssertEqual(decoded, expected) + } + + func testEncodeDecodeRetryPolicy() throws { + let policy = RetryPolicy( + maximumAttempts: 1, + initialBackoff: .seconds(1), + maximumBackoff: .seconds(3), + backoffMultiplier: 1.6, + retryableStatusCodes: [.aborted] + ) + + let encoded = try self.encoder.encode(policy) + let decoded = try self.decoder.decode(RetryPolicy.self, from: encoded) + XCTAssertEqual(decoded, policy) + } + + func testDecodeRetryPolicyWithInvalidRetryMaxAttempts() throws { + let json = """ + { + "maxAttempts": -1, + "initialBackoff": "1s", + "maxBackoff": "3s", + "backoffMultiplier": 1.6, + "retryableStatusCodes": ["ABORTED"] + } + """ + + try self.testDecodeThrowsRuntimeError(json: json, as: RetryPolicy.self) + } + + func testDecodeRetryPolicyWithInvalidInitialBackoff() throws { + let cases = ["0s", "-1s"] + for backoff in cases { + let json = """ + { + "maxAttempts": -1, + "initialBackoff": "\(backoff)", + "maxBackoff": "3s", + "backoffMultiplier": 1.6, + "retryableStatusCodes": ["ABORTED"] + } + """ + try self.testDecodeThrowsRuntimeError(json: json, as: RetryPolicy.self) + } + } + + func testDecodeRetryPolicyWithInvalidMaxBackoff() throws { + let cases = ["0s", "-1s"] + for backoff in cases { + let json = """ + { + "maxAttempts": -1, + "initialBackoff": "1s", + "maxBackoff": "\(backoff)", + "backoffMultiplier": 1.6, + "retryableStatusCodes": ["ABORTED"] + } + """ + try self.testDecodeThrowsRuntimeError(json: json, as: RetryPolicy.self) + } + } + + func testDecodeRetryPolicyWithInvalidBackoffMultiplier() throws { + let cases = ["0", "-1.5"] + for multiplier in cases { + let json = """ + { + "maxAttempts": -1, + "initialBackoff": "1s", + "maxBackoff": "3s", + "backoffMultiplier": \(multiplier), + "retryableStatusCodes": ["ABORTED"] + } + """ + try self.testDecodeThrowsRuntimeError(json: json, as: RetryPolicy.self) + } + } + + func testDecodeRetryPolicyWithEmptyRetryableStatusCodes() throws { + let json = """ + { + "maxAttempts": -1, + "initialBackoff": "1s", + "maxBackoff": "3s", + "backoffMultiplier": 1, + "retryableStatusCodes": [] + } + """ + try self.testDecodeThrowsRuntimeError(json: json, as: RetryPolicy.self) + } + + func testDecodeHedgingPolicy() throws { + let json = """ + { + "maxAttempts": 3, + "hedgingDelay": "1s", + "nonFatalStatusCodes": ["ABORTED"] + } + """ + + let expected = HedgingPolicy( + maximumAttempts: 3, + hedgingDelay: .seconds(1), + nonFatalStatusCodes: [.aborted] + ) + + let decoded = try self.decoder.decode(HedgingPolicy.self, from: Data(json.utf8)) + XCTAssertEqual(decoded, expected) + } + + func testEncodeDecodeHedgingPolicy() throws { + let policy = HedgingPolicy( + maximumAttempts: 3, + hedgingDelay: .seconds(1), + nonFatalStatusCodes: [.aborted] + ) + + let encoded = try self.encoder.encode(policy) + let decoded = try self.decoder.decode(HedgingPolicy.self, from: encoded) + XCTAssertEqual(decoded, policy) + } + + func testMethodConfigDecodeFromJSON() throws { + let config = Grpc_ServiceConfig_MethodConfig.with { + $0.name = [ + .with { + $0.service = "echo.Echo" + $0.method = "Get" + } + ] + + $0.timeout = .with { + $0.seconds = 1 + $0.nanos = 0 + } + + $0.maxRequestMessageBytes = 1024 + $0.maxResponseMessageBytes = 2048 + } + + // Test the 'regular' config. + do { + let jsonConfig = try config.jsonUTF8Data() + let decoded = try self.decoder.decode(MethodConfiguration.self, from: jsonConfig) + XCTAssertEqual(decoded.names, [MethodConfiguration.Name(service: "echo.Echo", method: "Get")]) + XCTAssertEqual(decoded.timeout, Duration(secondsComponent: 1, attosecondsComponent: 0)) + XCTAssertEqual(decoded.maxRequestMessageBytes, 1024) + XCTAssertEqual(decoded.maxResponseMessageBytes, 2048) + XCTAssertNil(decoded.executionPolicy) + } + + // Test the hedging policy. + do { + var config = config + config.hedgingPolicy = .with { + $0.maxAttempts = 3 + $0.hedgingDelay = .with { $0.seconds = 42 } + $0.nonFatalStatusCodes = [ + .aborted, + .unimplemented, + ] + } + + let jsonConfig = try config.jsonUTF8Data() + let decoded = try self.decoder.decode(MethodConfiguration.self, from: jsonConfig) + + switch decoded.executionPolicy { + case let .some(.hedge(policy)): + XCTAssertEqual(policy.maximumAttempts, 3) + XCTAssertEqual(policy.hedgingDelay, .seconds(42)) + XCTAssertEqual(policy.nonFatalStatusCodes, [.aborted, .unimplemented]) + default: + XCTFail("Expected hedging policy") + } + } + + // Test the retry policy. + do { + var config = config + config.retryPolicy = .with { + $0.maxAttempts = 3 + $0.initialBackoff = .with { $0.seconds = 1 } + $0.maxBackoff = .with { $0.seconds = 3 } + $0.backoffMultiplier = 1.6 + $0.retryableStatusCodes = [ + .aborted, + .unimplemented, + ] + } + + let jsonConfig = try config.jsonUTF8Data() + let decoded = try self.decoder.decode(MethodConfiguration.self, from: jsonConfig) + + switch decoded.executionPolicy { + case let .some(.retry(policy)): + XCTAssertEqual(policy.maximumAttempts, 3) + XCTAssertEqual(policy.initialBackoff, .seconds(1)) + XCTAssertEqual(policy.maximumBackoff, .seconds(3)) + XCTAssertEqual(policy.backoffMultiplier, 1.6) + XCTAssertEqual(policy.retryableStatusCodes, [.aborted, .unimplemented]) + default: + XCTFail("Expected hedging policy") + } + } + } +} diff --git a/Tests/GRPCCoreTests/MethodConfigurationTests.swift b/Tests/GRPCCoreTests/Configuration/MethodConfigurationTests.swift similarity index 100% rename from Tests/GRPCCoreTests/MethodConfigurationTests.swift rename to Tests/GRPCCoreTests/Configuration/MethodConfigurationTests.swift diff --git a/Tests/GRPCCoreTests/Configuration/ServiceConfigurationCodingTests.swift b/Tests/GRPCCoreTests/Configuration/ServiceConfigurationCodingTests.swift new file mode 100644 index 000000000..2dc8a943e --- /dev/null +++ b/Tests/GRPCCoreTests/Configuration/ServiceConfigurationCodingTests.swift @@ -0,0 +1,261 @@ +/* + * Copyright 2024, gRPC Authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Foundation +import GRPCCore +import XCTest + +@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) +final class ServiceConfigurationCodingTests: XCTestCase { + private let encoder = JSONEncoder() + private let decoder = JSONDecoder() + + private func testDecodeThrowsRuntimeError(json: String, as: D.Type) throws { + XCTAssertThrowsError( + ofType: RuntimeError.self, + try self.decoder.decode(D.self, from: Data(json.utf8)) + ) { error in + XCTAssertEqual(error.code, .invalidArgument) + } + } + + private func testRoundTripEncodeDecode(_ value: C) throws { + let encoded = try self.encoder.encode(value) + let decoded = try self.decoder.decode(C.self, from: encoded) + XCTAssertEqual(decoded, value) + } + + func testDecodeRetryThrottlingPolicy() throws { + let json = """ + { + "maxTokens": 10, + "tokenRatio": 0.5 + } + """ + + let expected = try ServiceConfiguration.RetryThrottlingPolicy(maxTokens: 10, tokenRatio: 0.5) + let policy = try self.decoder.decode( + ServiceConfiguration.RetryThrottlingPolicy.self, + from: Data(json.utf8) + ) + + XCTAssertEqual(policy, expected) + } + + func testEncodeDecodeRetryThrottlingPolicy() throws { + let policy = try ServiceConfiguration.RetryThrottlingPolicy(maxTokens: 10, tokenRatio: 0.5) + try self.testRoundTripEncodeDecode(policy) + } + + func testDecodeRetryThrottlingPolicyWithInvalidTokens() throws { + let inputs = ["0", "-1", "-42"] + for input in inputs { + let json = """ + { + "maxTokens": \(input), + "tokenRatio": 0.5 + } + """ + + try self.testDecodeThrowsRuntimeError( + json: json, + as: ServiceConfiguration.RetryThrottlingPolicy.self + ) + } + } + + func testDecodeRetryThrottlingPolicyWithInvalidTokenRatio() throws { + let inputs = ["0.0", "-1.0", "-42"] + for input in inputs { + let json = """ + { + "maxTokens": 10, + "tokenRatio": \(input) + } + """ + + try self.testDecodeThrowsRuntimeError( + json: json, + as: ServiceConfiguration.RetryThrottlingPolicy.self + ) + } + } + + func testDecodePickFirstPolicy() throws { + let inputs: [(String, ServiceConfiguration.LoadBalancingConfiguration.PickFirst)] = [ + (#"{"shuffleAddressList": true}"#, .init(shuffleAddressList: true)), + (#"{"shuffleAddressList": false}"#, .init(shuffleAddressList: false)), + (#"{}"#, .init(shuffleAddressList: false)), + ] + + for (input, expected) in inputs { + let pickFirst = try self.decoder.decode( + ServiceConfiguration.LoadBalancingConfiguration.PickFirst.self, + from: Data(input.utf8) + ) + + XCTAssertEqual(pickFirst, expected) + } + } + + func testEncodePickFirstPolicy() throws { + let inputs: [(ServiceConfiguration.LoadBalancingConfiguration.PickFirst, String)] = [ + (.init(shuffleAddressList: true), #"{"shuffleAddressList":true}"#), + (.init(shuffleAddressList: false), #"{"shuffleAddressList":false}"#), + ] + + for (input, expected) in inputs { + let encoded = try self.encoder.encode(input) + XCTAssertEqual(String(decoding: encoded, as: UTF8.self), expected) + } + } + + func testDecodeRoundRobinPolicy() throws { + let json = "{}" + let policy = try self.decoder.decode( + ServiceConfiguration.LoadBalancingConfiguration.RoundRobin.self, + from: Data(json.utf8) + ) + XCTAssertEqual(policy, ServiceConfiguration.LoadBalancingConfiguration.RoundRobin()) + } + + func testEncodeRoundRobinPolicy() throws { + let policy = ServiceConfiguration.LoadBalancingConfiguration.RoundRobin() + let encoded = try self.encoder.encode(policy) + XCTAssertEqual(String(decoding: encoded, as: UTF8.self), "{}") + } + + func testDecodeLoadBalancingConfiguration() throws { + let inputs: [(String, ServiceConfiguration.LoadBalancingConfiguration)] = [ + (#"{"round_robin": {}}"#, .roundRobin), + (#"{"pick_first": {}}"#, .pickFirst(shuffleAddressList: false)), + (#"{"pick_first": {"shuffleAddressList": false}}"#, .pickFirst(shuffleAddressList: false)), + ] + + for (input, expected) in inputs { + let decoded = try self.decoder.decode( + ServiceConfiguration.LoadBalancingConfiguration.self, + from: Data(input.utf8) + ) + XCTAssertEqual(decoded, expected) + } + } + + func testEncodeLoadBalancingConfiguration() throws { + let inputs: [(ServiceConfiguration.LoadBalancingConfiguration, String)] = [ + (.roundRobin, #"{"round_robin":{}}"#), + (.pickFirst(shuffleAddressList: false), #"{"pick_first":{"shuffleAddressList":false}}"#), + ] + + for (input, expected) in inputs { + let encoded = try self.encoder.encode(input) + XCTAssertEqual(String(decoding: encoded, as: UTF8.self), expected) + } + } + + func testDecodeServiceConfigurationFromProtoJSON() throws { + let serviceConfig = Grpc_ServiceConfig_ServiceConfig.with { + $0.methodConfig = [ + Grpc_ServiceConfig_MethodConfig.with { + $0.name = [ + Grpc_ServiceConfig_MethodConfig.Name.with { + $0.service = "foo.Foo" + $0.method = "Bar" + } + ] + $0.timeout = .with { $0.seconds = 1 } + $0.maxRequestMessageBytes = 123 + $0.maxResponseMessageBytes = 456 + } + + ] + $0.loadBalancingConfig = [ + .with { $0.roundRobin = .init() }, + .with { $0.pickFirst = .with { $0.shuffleAddressList = true } }, + ] + $0.retryThrottling = .with { + $0.maxTokens = 10 + $0.tokenRatio = 0.1 + } + } + + let encoded = try serviceConfig.jsonUTF8Data() + let decoded = try self.decoder.decode(ServiceConfiguration.self, from: encoded) + + let expected = ServiceConfiguration( + methodConfiguration: [ + MethodConfiguration( + names: [ + MethodConfiguration.Name(service: "foo.Foo", method: "Bar") + ], + timeout: .seconds(1), + maxRequestMessageBytes: 123, + maxResponseMessageBytes: 456 + ) + ], + loadBalancingConfiguration: [ + .roundRobin, + .pickFirst(shuffleAddressList: true), + ], + retryThrottlingPolicy: try ServiceConfiguration.RetryThrottlingPolicy( + maxTokens: 10, + tokenRatio: 0.1 + ) + ) + + XCTAssertEqual(decoded, expected) + } + + func testEncodeAndDecodeServiceConfiguration() throws { + let serviceConfig = ServiceConfiguration( + methodConfiguration: [ + MethodConfiguration( + names: [ + MethodConfiguration.Name(service: "echo.Echo", method: "Get"), + MethodConfiguration.Name(service: "greeter.HelloWorld"), + ], + timeout: .seconds(42), + maxRequestMessageBytes: 2048, + maxResponseMessageBytes: 4096, + executionPolicy: .hedge( + HedgingPolicy( + maximumAttempts: 3, + hedgingDelay: .seconds(1), + nonFatalStatusCodes: [.aborted] + ) + ) + ), + MethodConfiguration( + names: [ + MethodConfiguration.Name(service: "echo.Echo", method: "Update") + ], + timeout: .seconds(300), + maxRequestMessageBytes: 10_000 + ), + ], + loadBalancingConfiguration: [ + .pickFirst(shuffleAddressList: true), + .roundRobin, + ], + retryThrottlingPolicy: try ServiceConfiguration.RetryThrottlingPolicy( + maxTokens: 10, + tokenRatio: 3.141 + ) + ) + + try self.testRoundTripEncodeDecode(serviceConfig) + } +} diff --git a/Tests/GRPCCoreTests/MethodConfigurationsTests.swift b/Tests/GRPCCoreTests/MethodConfigurationsTests.swift index 0d8e88829..165b5a134 100644 --- a/Tests/GRPCCoreTests/MethodConfigurationsTests.swift +++ b/Tests/GRPCCoreTests/MethodConfigurationsTests.swift @@ -24,7 +24,7 @@ final class MethodConfigurationsTests: XCTestCase { hedgingDelay: .seconds(1), nonFatalStatusCodes: [] ) - let defaultConfiguration = MethodConfiguration(hedgingPolicy: policy) + let defaultConfiguration = MethodConfiguration(names: [], executionPolicy: .hedge(policy)) var configurations = MethodConfigurations() configurations.setDefaultConfiguration(defaultConfiguration) let descriptor = MethodDescriptor(service: "test", method: "first") @@ -35,7 +35,7 @@ final class MethodConfigurationsTests: XCTestCase { backoffMultiplier: 1.0, retryableStatusCodes: [.unavailable] ) - let overrideConfiguration = MethodConfiguration(retryPolicy: retryPolicy) + let overrideConfiguration = MethodConfiguration(names: [], executionPolicy: .retry(retryPolicy)) configurations[descriptor] = overrideConfiguration XCTAssertEqual(configurations[descriptor], overrideConfiguration) @@ -47,7 +47,7 @@ final class MethodConfigurationsTests: XCTestCase { hedgingDelay: .seconds(1), nonFatalStatusCodes: [] ) - let defaultConfiguration = MethodConfiguration(hedgingPolicy: policy) + let defaultConfiguration = MethodConfiguration(names: [], executionPolicy: .hedge(policy)) var configurations = MethodConfigurations() configurations.setDefaultConfiguration(defaultConfiguration) let firstDescriptor = MethodDescriptor(service: "test", method: "") @@ -58,7 +58,7 @@ final class MethodConfigurationsTests: XCTestCase { backoffMultiplier: 1.0, retryableStatusCodes: [.unavailable] ) - let overrideConfiguration = MethodConfiguration(retryPolicy: retryPolicy) + let overrideConfiguration = MethodConfiguration(names: [], executionPolicy: .retry(retryPolicy)) configurations[firstDescriptor] = overrideConfiguration let secondDescriptor = MethodDescriptor(service: "test", method: "second") @@ -71,7 +71,7 @@ final class MethodConfigurationsTests: XCTestCase { hedgingDelay: .seconds(1), nonFatalStatusCodes: [] ) - let defaultConfiguration = MethodConfiguration(hedgingPolicy: policy) + let defaultConfiguration = MethodConfiguration(names: [], executionPolicy: .hedge(policy)) var configurations = MethodConfigurations() configurations.setDefaultConfiguration(defaultConfiguration) let firstDescriptor = MethodDescriptor(service: "test1", method: "first") @@ -82,7 +82,7 @@ final class MethodConfigurationsTests: XCTestCase { backoffMultiplier: 1.0, retryableStatusCodes: [.unavailable] ) - let overrideConfiguration = MethodConfiguration(retryPolicy: retryPolicy) + let overrideConfiguration = MethodConfiguration(names: [], executionPolicy: .retry(retryPolicy)) configurations[firstDescriptor] = overrideConfiguration let secondDescriptor = MethodDescriptor(service: "test2", method: "second") diff --git a/Tests/GRPCInProcessTransportTests/InProcessClientTransportTests.swift b/Tests/GRPCInProcessTransportTests/InProcessClientTransportTests.swift index 7aa64d05c..18209ac01 100644 --- a/Tests/GRPCInProcessTransportTests/InProcessClientTransportTests.swift +++ b/Tests/GRPCInProcessTransportTests/InProcessClientTransportTests.swift @@ -187,7 +187,7 @@ final class InProcessClientTransportTests: XCTestCase { hedgingDelay: .seconds(1), nonFatalStatusCodes: [] ) - let defaultConfiguration = MethodConfiguration(hedgingPolicy: policy) + let defaultConfiguration = MethodConfiguration(names: [], executionPolicy: .hedge(policy)) var configurations = MethodConfigurations() configurations.setDefaultConfiguration(defaultConfiguration) @@ -203,7 +203,7 @@ final class InProcessClientTransportTests: XCTestCase { backoffMultiplier: 1.0, retryableStatusCodes: [.unavailable] ) - let overrideConfiguration = MethodConfiguration(retryPolicy: retryPolicy) + let overrideConfiguration = MethodConfiguration(names: [], executionPolicy: .retry(retryPolicy)) configurations[firstDescriptor] = overrideConfiguration client = InProcessClientTransport(server: .init(), methodConfiguration: configurations) let secondDescriptor = MethodDescriptor(service: "test", method: "second") @@ -255,7 +255,7 @@ final class InProcessClientTransportTests: XCTestCase { var methodConfiguration = MethodConfigurations() methodConfiguration.setDefaultConfiguration( - configuration ?? .init(retryPolicy: defaultPolicy) + configuration ?? .init(names: [], executionPolicy: .retry(defaultPolicy)) ) return InProcessClientTransport( server: server, From 10aac1d2a905c7438b679dc15597ab727f2b35a8 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Fri, 2 Feb 2024 15:06:05 +0000 Subject: [PATCH 2/6] Add service_config proto and generate --- Package.swift | 3 +- Protos/generate.sh | 15 + .../Configuration/Generated/code.pb.swift | 307 ++ .../Configuration/Generated/rls.pb.swift | 253 + .../Generated/rls_config.pb.swift | 707 +++ .../Generated/service_config.pb.swift | 4149 +++++++++++++++++ 6 files changed, 5433 insertions(+), 1 deletion(-) create mode 100644 Tests/GRPCCoreTests/Configuration/Generated/code.pb.swift create mode 100644 Tests/GRPCCoreTests/Configuration/Generated/rls.pb.swift create mode 100644 Tests/GRPCCoreTests/Configuration/Generated/rls_config.pb.swift create mode 100644 Tests/GRPCCoreTests/Configuration/Generated/service_config.pb.swift diff --git a/Package.swift b/Package.swift index b864f5944..f21b2a5e2 100644 --- a/Package.swift +++ b/Package.swift @@ -286,7 +286,8 @@ extension Target { .grpcCore, .grpcInProcessTransport, .dequeModule, - .atomics + .atomics, + .protobuf, ] ) diff --git a/Protos/generate.sh b/Protos/generate.sh index 22a916417..686ef632d 100755 --- a/Protos/generate.sh +++ b/Protos/generate.sh @@ -172,6 +172,20 @@ function generate_reflection_data_example { done } +function generate_rpc_code_for_tests { + local protos=( + "$here/upstream/grpc/service_config/service_config.proto" + "$here/upstream/grpc/lookup/v1/rls.proto" + "$here/upstream/grpc/lookup/v1/rls_config.proto" + "$here/upstream/google/rpc/code.proto" + ) + local output="$root/Tests/GRPCCoreTests/Configuration/Generated" + + for proto in "${protos[@]}"; do + generate_message "$proto" "$here/upstream" "$output" "Visibility=Internal" "FileNaming=DropPath" + done +} + #------------------------------------------------------------------------------ # Examples @@ -187,3 +201,4 @@ generate_echo_reflection_data_for_tests # Misc. tests generate_normalization_for_tests +generate_rpc_code_for_tests diff --git a/Tests/GRPCCoreTests/Configuration/Generated/code.pb.swift b/Tests/GRPCCoreTests/Configuration/Generated/code.pb.swift new file mode 100644 index 000000000..a7c135fd0 --- /dev/null +++ b/Tests/GRPCCoreTests/Configuration/Generated/code.pb.swift @@ -0,0 +1,307 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: google/rpc/code.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +/// The canonical error codes for gRPC APIs. +/// +/// +/// Sometimes multiple error codes may apply. Services should return +/// the most specific error code that applies. For example, prefer +/// `OUT_OF_RANGE` over `FAILED_PRECONDITION` if both codes apply. +/// Similarly prefer `NOT_FOUND` or `ALREADY_EXISTS` over `FAILED_PRECONDITION`. +enum Google_Rpc_Code: SwiftProtobuf.Enum { + typealias RawValue = Int + + /// Not an error; returned on success. + /// + /// HTTP Mapping: 200 OK + case ok // = 0 + + /// The operation was cancelled, typically by the caller. + /// + /// HTTP Mapping: 499 Client Closed Request + case cancelled // = 1 + + /// Unknown error. For example, this error may be returned when + /// a `Status` value received from another address space belongs to + /// an error space that is not known in this address space. Also + /// errors raised by APIs that do not return enough error information + /// may be converted to this error. + /// + /// HTTP Mapping: 500 Internal Server Error + case unknown // = 2 + + /// The client specified an invalid argument. Note that this differs + /// from `FAILED_PRECONDITION`. `INVALID_ARGUMENT` indicates arguments + /// that are problematic regardless of the state of the system + /// (e.g., a malformed file name). + /// + /// HTTP Mapping: 400 Bad Request + case invalidArgument // = 3 + + /// The deadline expired before the operation could complete. For operations + /// that change the state of the system, this error may be returned + /// even if the operation has completed successfully. For example, a + /// successful response from a server could have been delayed long + /// enough for the deadline to expire. + /// + /// HTTP Mapping: 504 Gateway Timeout + case deadlineExceeded // = 4 + + /// Some requested entity (e.g., file or directory) was not found. + /// + /// Note to server developers: if a request is denied for an entire class + /// of users, such as gradual feature rollout or undocumented allowlist, + /// `NOT_FOUND` may be used. If a request is denied for some users within + /// a class of users, such as user-based access control, `PERMISSION_DENIED` + /// must be used. + /// + /// HTTP Mapping: 404 Not Found + case notFound // = 5 + + /// The entity that a client attempted to create (e.g., file or directory) + /// already exists. + /// + /// HTTP Mapping: 409 Conflict + case alreadyExists // = 6 + + /// The caller does not have permission to execute the specified + /// operation. `PERMISSION_DENIED` must not be used for rejections + /// caused by exhausting some resource (use `RESOURCE_EXHAUSTED` + /// instead for those errors). `PERMISSION_DENIED` must not be + /// used if the caller can not be identified (use `UNAUTHENTICATED` + /// instead for those errors). This error code does not imply the + /// request is valid or the requested entity exists or satisfies + /// other pre-conditions. + /// + /// HTTP Mapping: 403 Forbidden + case permissionDenied // = 7 + + /// The request does not have valid authentication credentials for the + /// operation. + /// + /// HTTP Mapping: 401 Unauthorized + case unauthenticated // = 16 + + /// Some resource has been exhausted, perhaps a per-user quota, or + /// perhaps the entire file system is out of space. + /// + /// HTTP Mapping: 429 Too Many Requests + case resourceExhausted // = 8 + + /// The operation was rejected because the system is not in a state + /// required for the operation's execution. For example, the directory + /// to be deleted is non-empty, an rmdir operation is applied to + /// a non-directory, etc. + /// + /// Service implementors can use the following guidelines to decide + /// between `FAILED_PRECONDITION`, `ABORTED`, and `UNAVAILABLE`: + /// (a) Use `UNAVAILABLE` if the client can retry just the failing call. + /// (b) Use `ABORTED` if the client should retry at a higher level. For + /// example, when a client-specified test-and-set fails, indicating the + /// client should restart a read-modify-write sequence. + /// (c) Use `FAILED_PRECONDITION` if the client should not retry until + /// the system state has been explicitly fixed. For example, if an "rmdir" + /// fails because the directory is non-empty, `FAILED_PRECONDITION` + /// should be returned since the client should not retry unless + /// the files are deleted from the directory. + /// + /// HTTP Mapping: 400 Bad Request + case failedPrecondition // = 9 + + /// The operation was aborted, typically due to a concurrency issue such as + /// a sequencer check failure or transaction abort. + /// + /// See the guidelines above for deciding between `FAILED_PRECONDITION`, + /// `ABORTED`, and `UNAVAILABLE`. + /// + /// HTTP Mapping: 409 Conflict + case aborted // = 10 + + /// The operation was attempted past the valid range. E.g., seeking or + /// reading past end-of-file. + /// + /// Unlike `INVALID_ARGUMENT`, this error indicates a problem that may + /// be fixed if the system state changes. For example, a 32-bit file + /// system will generate `INVALID_ARGUMENT` if asked to read at an + /// offset that is not in the range [0,2^32-1], but it will generate + /// `OUT_OF_RANGE` if asked to read from an offset past the current + /// file size. + /// + /// There is a fair bit of overlap between `FAILED_PRECONDITION` and + /// `OUT_OF_RANGE`. We recommend using `OUT_OF_RANGE` (the more specific + /// error) when it applies so that callers who are iterating through + /// a space can easily look for an `OUT_OF_RANGE` error to detect when + /// they are done. + /// + /// HTTP Mapping: 400 Bad Request + case outOfRange // = 11 + + /// The operation is not implemented or is not supported/enabled in this + /// service. + /// + /// HTTP Mapping: 501 Not Implemented + case unimplemented // = 12 + + /// Internal errors. This means that some invariants expected by the + /// underlying system have been broken. This error code is reserved + /// for serious errors. + /// + /// HTTP Mapping: 500 Internal Server Error + case `internal` // = 13 + + /// The service is currently unavailable. This is most likely a + /// transient condition, which can be corrected by retrying with + /// a backoff. Note that it is not always safe to retry + /// non-idempotent operations. + /// + /// See the guidelines above for deciding between `FAILED_PRECONDITION`, + /// `ABORTED`, and `UNAVAILABLE`. + /// + /// HTTP Mapping: 503 Service Unavailable + case unavailable // = 14 + + /// Unrecoverable data loss or corruption. + /// + /// HTTP Mapping: 500 Internal Server Error + case dataLoss // = 15 + case UNRECOGNIZED(Int) + + init() { + self = .ok + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .ok + case 1: self = .cancelled + case 2: self = .unknown + case 3: self = .invalidArgument + case 4: self = .deadlineExceeded + case 5: self = .notFound + case 6: self = .alreadyExists + case 7: self = .permissionDenied + case 8: self = .resourceExhausted + case 9: self = .failedPrecondition + case 10: self = .aborted + case 11: self = .outOfRange + case 12: self = .unimplemented + case 13: self = .internal + case 14: self = .unavailable + case 15: self = .dataLoss + case 16: self = .unauthenticated + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .ok: return 0 + case .cancelled: return 1 + case .unknown: return 2 + case .invalidArgument: return 3 + case .deadlineExceeded: return 4 + case .notFound: return 5 + case .alreadyExists: return 6 + case .permissionDenied: return 7 + case .resourceExhausted: return 8 + case .failedPrecondition: return 9 + case .aborted: return 10 + case .outOfRange: return 11 + case .unimplemented: return 12 + case .internal: return 13 + case .unavailable: return 14 + case .dataLoss: return 15 + case .unauthenticated: return 16 + case .UNRECOGNIZED(let i): return i + } + } + +} + +#if swift(>=4.2) + +extension Google_Rpc_Code: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static let allCases: [Google_Rpc_Code] = [ + .ok, + .cancelled, + .unknown, + .invalidArgument, + .deadlineExceeded, + .notFound, + .alreadyExists, + .permissionDenied, + .unauthenticated, + .resourceExhausted, + .failedPrecondition, + .aborted, + .outOfRange, + .unimplemented, + .internal, + .unavailable, + .dataLoss, + ] +} + +#endif // swift(>=4.2) + +#if swift(>=5.5) && canImport(_Concurrency) +extension Google_Rpc_Code: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +extension Google_Rpc_Code: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "OK"), + 1: .same(proto: "CANCELLED"), + 2: .same(proto: "UNKNOWN"), + 3: .same(proto: "INVALID_ARGUMENT"), + 4: .same(proto: "DEADLINE_EXCEEDED"), + 5: .same(proto: "NOT_FOUND"), + 6: .same(proto: "ALREADY_EXISTS"), + 7: .same(proto: "PERMISSION_DENIED"), + 8: .same(proto: "RESOURCE_EXHAUSTED"), + 9: .same(proto: "FAILED_PRECONDITION"), + 10: .same(proto: "ABORTED"), + 11: .same(proto: "OUT_OF_RANGE"), + 12: .same(proto: "UNIMPLEMENTED"), + 13: .same(proto: "INTERNAL"), + 14: .same(proto: "UNAVAILABLE"), + 15: .same(proto: "DATA_LOSS"), + 16: .same(proto: "UNAUTHENTICATED"), + ] +} diff --git a/Tests/GRPCCoreTests/Configuration/Generated/rls.pb.swift b/Tests/GRPCCoreTests/Configuration/Generated/rls.pb.swift new file mode 100644 index 000000000..8300d1877 --- /dev/null +++ b/Tests/GRPCCoreTests/Configuration/Generated/rls.pb.swift @@ -0,0 +1,253 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: grpc/lookup/v1/rls.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +// Copyright 2020 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +struct Grpc_Lookup_V1_RouteLookupRequest { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Target type allows the client to specify what kind of target format it + /// would like from RLS to allow it to find the regional server, e.g. "grpc". + var targetType: String = String() + + /// Reason for making this request. + var reason: Grpc_Lookup_V1_RouteLookupRequest.Reason = .unknown + + /// For REASON_STALE, the header_data from the stale response, if any. + var staleHeaderData: String = String() + + /// Map of key values extracted via key builders for the gRPC or HTTP request. + var keyMap: Dictionary = [:] + + /// Application-specific optional extensions. + var extensions: [SwiftProtobuf.Google_Protobuf_Any] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + /// Possible reasons for making a request. + enum Reason: SwiftProtobuf.Enum { + typealias RawValue = Int + + /// Unused + case unknown // = 0 + + /// No data available in local cache + case miss // = 1 + + /// Data in local cache is stale + case stale // = 2 + case UNRECOGNIZED(Int) + + init() { + self = .unknown + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .unknown + case 1: self = .miss + case 2: self = .stale + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .unknown: return 0 + case .miss: return 1 + case .stale: return 2 + case .UNRECOGNIZED(let i): return i + } + } + + } + + init() {} +} + +#if swift(>=4.2) + +extension Grpc_Lookup_V1_RouteLookupRequest.Reason: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static let allCases: [Grpc_Lookup_V1_RouteLookupRequest.Reason] = [ + .unknown, + .miss, + .stale, + ] +} + +#endif // swift(>=4.2) + +struct Grpc_Lookup_V1_RouteLookupResponse { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Prioritized list (best one first) of addressable entities to use + /// for routing, using syntax requested by the request target_type. + /// The targets will be tried in order until a healthy one is found. + var targets: [String] = [] + + /// Optional header value to pass along to AFE in the X-Google-RLS-Data header. + /// Cached with "target" and sent with all requests that match the request key. + /// Allows the RLS to pass its work product to the eventual target. + var headerData: String = String() + + /// Application-specific optional extensions. + var extensions: [SwiftProtobuf.Google_Protobuf_Any] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +#if swift(>=5.5) && canImport(_Concurrency) +extension Grpc_Lookup_V1_RouteLookupRequest: @unchecked Sendable {} +extension Grpc_Lookup_V1_RouteLookupRequest.Reason: @unchecked Sendable {} +extension Grpc_Lookup_V1_RouteLookupResponse: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +fileprivate let _protobuf_package = "grpc.lookup.v1" + +extension Grpc_Lookup_V1_RouteLookupRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".RouteLookupRequest" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 3: .standard(proto: "target_type"), + 5: .same(proto: "reason"), + 6: .standard(proto: "stale_header_data"), + 4: .standard(proto: "key_map"), + 7: .same(proto: "extensions"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 3: try { try decoder.decodeSingularStringField(value: &self.targetType) }() + case 4: try { try decoder.decodeMapField(fieldType: SwiftProtobuf._ProtobufMap.self, value: &self.keyMap) }() + case 5: try { try decoder.decodeSingularEnumField(value: &self.reason) }() + case 6: try { try decoder.decodeSingularStringField(value: &self.staleHeaderData) }() + case 7: try { try decoder.decodeRepeatedMessageField(value: &self.extensions) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.targetType.isEmpty { + try visitor.visitSingularStringField(value: self.targetType, fieldNumber: 3) + } + if !self.keyMap.isEmpty { + try visitor.visitMapField(fieldType: SwiftProtobuf._ProtobufMap.self, value: self.keyMap, fieldNumber: 4) + } + if self.reason != .unknown { + try visitor.visitSingularEnumField(value: self.reason, fieldNumber: 5) + } + if !self.staleHeaderData.isEmpty { + try visitor.visitSingularStringField(value: self.staleHeaderData, fieldNumber: 6) + } + if !self.extensions.isEmpty { + try visitor.visitRepeatedMessageField(value: self.extensions, fieldNumber: 7) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_Lookup_V1_RouteLookupRequest, rhs: Grpc_Lookup_V1_RouteLookupRequest) -> Bool { + if lhs.targetType != rhs.targetType {return false} + if lhs.reason != rhs.reason {return false} + if lhs.staleHeaderData != rhs.staleHeaderData {return false} + if lhs.keyMap != rhs.keyMap {return false} + if lhs.extensions != rhs.extensions {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_Lookup_V1_RouteLookupRequest.Reason: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "REASON_UNKNOWN"), + 1: .same(proto: "REASON_MISS"), + 2: .same(proto: "REASON_STALE"), + ] +} + +extension Grpc_Lookup_V1_RouteLookupResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".RouteLookupResponse" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 3: .same(proto: "targets"), + 2: .standard(proto: "header_data"), + 4: .same(proto: "extensions"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 2: try { try decoder.decodeSingularStringField(value: &self.headerData) }() + case 3: try { try decoder.decodeRepeatedStringField(value: &self.targets) }() + case 4: try { try decoder.decodeRepeatedMessageField(value: &self.extensions) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.headerData.isEmpty { + try visitor.visitSingularStringField(value: self.headerData, fieldNumber: 2) + } + if !self.targets.isEmpty { + try visitor.visitRepeatedStringField(value: self.targets, fieldNumber: 3) + } + if !self.extensions.isEmpty { + try visitor.visitRepeatedMessageField(value: self.extensions, fieldNumber: 4) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_Lookup_V1_RouteLookupResponse, rhs: Grpc_Lookup_V1_RouteLookupResponse) -> Bool { + if lhs.targets != rhs.targets {return false} + if lhs.headerData != rhs.headerData {return false} + if lhs.extensions != rhs.extensions {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} diff --git a/Tests/GRPCCoreTests/Configuration/Generated/rls_config.pb.swift b/Tests/GRPCCoreTests/Configuration/Generated/rls_config.pb.swift new file mode 100644 index 000000000..2d1e22104 --- /dev/null +++ b/Tests/GRPCCoreTests/Configuration/Generated/rls_config.pb.swift @@ -0,0 +1,707 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: grpc/lookup/v1/rls_config.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +// Copyright 2020 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +/// Extract a key based on a given name (e.g. header name or query parameter +/// name). The name must match one of the names listed in the "name" field. If +/// the "required_match" field is true, one of the specified names must be +/// present for the keybuilder to match. +struct Grpc_Lookup_V1_NameMatcher { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// The name that will be used in the RLS key_map to refer to this value. + /// If required_match is true, you may omit this field or set it to an empty + /// string, in which case the matcher will require a match, but won't update + /// the key_map. + var key: String = String() + + /// Ordered list of names (headers or query parameter names) that can supply + /// this value; the first one with a non-empty value is used. + var names: [String] = [] + + /// If true, make this extraction required; the key builder will not match + /// if no value is found. + var requiredMatch: Bool = false + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// A GrpcKeyBuilder applies to a given gRPC service, name, and headers. +struct Grpc_Lookup_V1_GrpcKeyBuilder { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var names: [Grpc_Lookup_V1_GrpcKeyBuilder.Name] = [] + + var extraKeys: Grpc_Lookup_V1_GrpcKeyBuilder.ExtraKeys { + get {return _extraKeys ?? Grpc_Lookup_V1_GrpcKeyBuilder.ExtraKeys()} + set {_extraKeys = newValue} + } + /// Returns true if `extraKeys` has been explicitly set. + var hasExtraKeys: Bool {return self._extraKeys != nil} + /// Clears the value of `extraKeys`. Subsequent reads from it will return its default value. + mutating func clearExtraKeys() {self._extraKeys = nil} + + /// Extract keys from all listed headers. + /// For gRPC, it is an error to specify "required_match" on the NameMatcher + /// protos. + var headers: [Grpc_Lookup_V1_NameMatcher] = [] + + /// You can optionally set one or more specific key/value pairs to be added to + /// the key_map. This can be useful to identify which builder built the key, + /// for example if you are suppressing the actual method, but need to + /// separately cache and request all the matched methods. + var constantKeys: Dictionary = [:] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + /// To match, one of the given Name fields must match; the service and method + /// fields are specified as fixed strings. The service name is required and + /// includes the proto package name. The method name may be omitted, in + /// which case any method on the given service is matched. + struct Name { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var service: String = String() + + var method: String = String() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + } + + /// If you wish to include the host, service, or method names as keys in the + /// generated RouteLookupRequest, specify key names to use in the extra_keys + /// submessage. If a key name is empty, no key will be set for that value. + /// If this submessage is specified, the normal host/path fields will be left + /// unset in the RouteLookupRequest. We are deprecating host/path in the + /// RouteLookupRequest, so services should migrate to the ExtraKeys approach. + struct ExtraKeys { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var host: String = String() + + var service: String = String() + + var method: String = String() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + } + + init() {} + + fileprivate var _extraKeys: Grpc_Lookup_V1_GrpcKeyBuilder.ExtraKeys? = nil +} + +/// An HttpKeyBuilder applies to a given HTTP URL and headers. +/// +/// Path and host patterns use the matching syntax from gRPC transcoding to +/// extract named key/value pairs from the path and host components of the URL: +/// https://github.com/googleapis/googleapis/blob/master/google/api/http.proto +/// +/// It is invalid to specify the same key name in multiple places in a pattern. +/// +/// For a service where the project id can be expressed either as a subdomain or +/// in the path, separate HttpKeyBuilders must be used: +/// host_pattern: 'example.com' path_pattern: '/{id}/{object}/**' +/// host_pattern: '{id}.example.com' path_pattern: '/{object}/**' +/// If the host is exactly 'example.com', the first path segment will be used as +/// the id and the second segment as the object. If the host has a subdomain, the +/// subdomain will be used as the id and the first segment as the object. If +/// neither pattern matches, no keys will be extracted. +struct Grpc_Lookup_V1_HttpKeyBuilder { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// host_pattern is an ordered list of host template patterns for the desired + /// value. If any host_pattern values are specified, then at least one must + /// match, and the last one wins and sets any specified variables. A host + /// consists of labels separated by dots. Each label is matched against the + /// label in the pattern as follows: + /// - "*": Matches any single label. + /// - "**": Matches zero or more labels (first or last part of host only). + /// - "{=...}": One or more label capture, where "..." can be any + /// template that does not include a capture. + /// - "{}": A single label capture. Identical to {=*}. + /// + /// Examples: + /// - "example.com": Only applies to the exact host example.com. + /// - "*.example.com": Matches subdomains of example.com. + /// - "**.example.com": matches example.com, and all levels of subdomains. + /// - "{project}.example.com": Extracts the third level subdomain. + /// - "{project=**}.example.com": Extracts the third level+ subdomains. + /// - "{project=**}": Extracts the entire host. + var hostPatterns: [String] = [] + + /// path_pattern is an ordered list of path template patterns for the desired + /// value. If any path_pattern values are specified, then at least one must + /// match, and the last one wins and sets any specified variables. A path + /// consists of segments separated by slashes. Each segment is matched against + /// the segment in the pattern as follows: + /// - "*": Matches any single segment. + /// - "**": Matches zero or more segments (first or last part of path only). + /// - "{=...}": One or more segment capture, where "..." can be any + /// template that does not include a capture. + /// - "{}": A single segment capture. Identical to {=*}. + /// A custom method may also be specified by appending ":" and the custom + /// method name or "*" to indicate any custom method (including no custom + /// method). For example, "/*/projects/{project_id}/**:*" extracts + /// `{project_id}` for any version, resource and custom method that includes + /// it. By default, any custom method will be matched. + /// + /// Examples: + /// - "/v1/{name=messages/*}": extracts a name like "messages/12345". + /// - "/v1/messages/{message_id}": extracts a message_id like "12345". + /// - "/v1/users/{user_id}/messages/{message_id}": extracts two key values. + var pathPatterns: [String] = [] + + /// List of query parameter names to try to match. + /// For example: ["parent", "name", "resource.name"] + /// We extract all the specified query_parameters (case-sensitively). If any + /// are marked as "required_match" and are not present, this keybuilder fails + /// to match. If a given parameter appears multiple times (?foo=a&foo=b) we + /// will report it as a comma-separated string (foo=a,b). + var queryParameters: [Grpc_Lookup_V1_NameMatcher] = [] + + /// List of headers to try to match. + /// We extract all the specified header values (case-insensitively). If any + /// are marked as "required_match" and are not present, this keybuilder fails + /// to match. If a given header appears multiple times in the request we will + /// report it as a comma-separated string, in standard HTTP fashion. + var headers: [Grpc_Lookup_V1_NameMatcher] = [] + + /// You can optionally set one or more specific key/value pairs to be added to + /// the key_map. This can be useful to identify which builder built the key, + /// for example if you are suppressing a lot of information from the URL, but + /// need to separately cache and request URLs with that content. + var constantKeys: Dictionary = [:] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct Grpc_Lookup_V1_RouteLookupConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Ordered specifications for constructing keys for HTTP requests. Last + /// match wins. If no HttpKeyBuilder matches, an empty key_map will be sent to + /// the lookup service; it should likely reply with a global default route + /// and raise an alert. + var httpKeybuilders: [Grpc_Lookup_V1_HttpKeyBuilder] = [] + + /// Unordered specifications for constructing keys for gRPC requests. All + /// GrpcKeyBuilders on this list must have unique "name" fields so that the + /// client is free to prebuild a hash map keyed by name. If no GrpcKeyBuilder + /// matches, an empty key_map will be sent to the lookup service; it should + /// likely reply with a global default route and raise an alert. + var grpcKeybuilders: [Grpc_Lookup_V1_GrpcKeyBuilder] = [] + + /// The name of the lookup service as a gRPC URI. Typically, this will be + /// a subdomain of the target, such as "lookup.datastore.googleapis.com". + var lookupService: String = String() + + /// Configure a timeout value for lookup service requests. + /// Defaults to 10 seconds if not specified. + var lookupServiceTimeout: SwiftProtobuf.Google_Protobuf_Duration { + get {return _lookupServiceTimeout ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_lookupServiceTimeout = newValue} + } + /// Returns true if `lookupServiceTimeout` has been explicitly set. + var hasLookupServiceTimeout: Bool {return self._lookupServiceTimeout != nil} + /// Clears the value of `lookupServiceTimeout`. Subsequent reads from it will return its default value. + mutating func clearLookupServiceTimeout() {self._lookupServiceTimeout = nil} + + /// How long are responses valid for (like HTTP Cache-Control). + /// If omitted or zero, the longest valid cache time is used. + /// This value is clamped to 5 minutes to avoid unflushable bad responses. + var maxAge: SwiftProtobuf.Google_Protobuf_Duration { + get {return _maxAge ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_maxAge = newValue} + } + /// Returns true if `maxAge` has been explicitly set. + var hasMaxAge: Bool {return self._maxAge != nil} + /// Clears the value of `maxAge`. Subsequent reads from it will return its default value. + mutating func clearMaxAge() {self._maxAge = nil} + + /// After a response has been in the client cache for this amount of time + /// and is re-requested, start an asynchronous RPC to re-validate it. + /// This value should be less than max_age by at least the length of a + /// typical RTT to the Route Lookup Service to fully mask the RTT latency. + /// If omitted, keys are only re-requested after they have expired. + var staleAge: SwiftProtobuf.Google_Protobuf_Duration { + get {return _staleAge ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_staleAge = newValue} + } + /// Returns true if `staleAge` has been explicitly set. + var hasStaleAge: Bool {return self._staleAge != nil} + /// Clears the value of `staleAge`. Subsequent reads from it will return its default value. + mutating func clearStaleAge() {self._staleAge = nil} + + /// Rough indicator of amount of memory to use for the client cache. Some of + /// the data structure overhead is not accounted for, so actual memory consumed + /// will be somewhat greater than this value. If this field is omitted or set + /// to zero, a client default will be used. The value may be capped to a lower + /// amount based on client configuration. + var cacheSizeBytes: Int64 = 0 + + /// This is a list of all the possible targets that can be returned by the + /// lookup service. If a target not on this list is returned, it will be + /// treated the same as an unhealthy target. + var validTargets: [String] = [] + + /// This value provides a default target to use if needed. If set, it will be + /// used if RLS returns an error, times out, or returns an invalid response. + /// Note that requests can be routed only to a subdomain of the original + /// target, e.g. "us_east_1.cloudbigtable.googleapis.com". + var defaultTarget: String = String() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _lookupServiceTimeout: SwiftProtobuf.Google_Protobuf_Duration? = nil + fileprivate var _maxAge: SwiftProtobuf.Google_Protobuf_Duration? = nil + fileprivate var _staleAge: SwiftProtobuf.Google_Protobuf_Duration? = nil +} + +/// RouteLookupClusterSpecifier is used in xDS to represent a cluster specifier +/// plugin for RLS. +struct Grpc_Lookup_V1_RouteLookupClusterSpecifier { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// The RLS config for this cluster specifier plugin instance. + var routeLookupConfig: Grpc_Lookup_V1_RouteLookupConfig { + get {return _routeLookupConfig ?? Grpc_Lookup_V1_RouteLookupConfig()} + set {_routeLookupConfig = newValue} + } + /// Returns true if `routeLookupConfig` has been explicitly set. + var hasRouteLookupConfig: Bool {return self._routeLookupConfig != nil} + /// Clears the value of `routeLookupConfig`. Subsequent reads from it will return its default value. + mutating func clearRouteLookupConfig() {self._routeLookupConfig = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _routeLookupConfig: Grpc_Lookup_V1_RouteLookupConfig? = nil +} + +#if swift(>=5.5) && canImport(_Concurrency) +extension Grpc_Lookup_V1_NameMatcher: @unchecked Sendable {} +extension Grpc_Lookup_V1_GrpcKeyBuilder: @unchecked Sendable {} +extension Grpc_Lookup_V1_GrpcKeyBuilder.Name: @unchecked Sendable {} +extension Grpc_Lookup_V1_GrpcKeyBuilder.ExtraKeys: @unchecked Sendable {} +extension Grpc_Lookup_V1_HttpKeyBuilder: @unchecked Sendable {} +extension Grpc_Lookup_V1_RouteLookupConfig: @unchecked Sendable {} +extension Grpc_Lookup_V1_RouteLookupClusterSpecifier: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +fileprivate let _protobuf_package = "grpc.lookup.v1" + +extension Grpc_Lookup_V1_NameMatcher: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".NameMatcher" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "key"), + 2: .same(proto: "names"), + 3: .standard(proto: "required_match"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.key) }() + case 2: try { try decoder.decodeRepeatedStringField(value: &self.names) }() + case 3: try { try decoder.decodeSingularBoolField(value: &self.requiredMatch) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.key.isEmpty { + try visitor.visitSingularStringField(value: self.key, fieldNumber: 1) + } + if !self.names.isEmpty { + try visitor.visitRepeatedStringField(value: self.names, fieldNumber: 2) + } + if self.requiredMatch != false { + try visitor.visitSingularBoolField(value: self.requiredMatch, fieldNumber: 3) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_Lookup_V1_NameMatcher, rhs: Grpc_Lookup_V1_NameMatcher) -> Bool { + if lhs.key != rhs.key {return false} + if lhs.names != rhs.names {return false} + if lhs.requiredMatch != rhs.requiredMatch {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_Lookup_V1_GrpcKeyBuilder: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".GrpcKeyBuilder" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "names"), + 3: .standard(proto: "extra_keys"), + 2: .same(proto: "headers"), + 4: .standard(proto: "constant_keys"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeRepeatedMessageField(value: &self.names) }() + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.headers) }() + case 3: try { try decoder.decodeSingularMessageField(value: &self._extraKeys) }() + case 4: try { try decoder.decodeMapField(fieldType: SwiftProtobuf._ProtobufMap.self, value: &self.constantKeys) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if !self.names.isEmpty { + try visitor.visitRepeatedMessageField(value: self.names, fieldNumber: 1) + } + if !self.headers.isEmpty { + try visitor.visitRepeatedMessageField(value: self.headers, fieldNumber: 2) + } + try { if let v = self._extraKeys { + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + } }() + if !self.constantKeys.isEmpty { + try visitor.visitMapField(fieldType: SwiftProtobuf._ProtobufMap.self, value: self.constantKeys, fieldNumber: 4) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_Lookup_V1_GrpcKeyBuilder, rhs: Grpc_Lookup_V1_GrpcKeyBuilder) -> Bool { + if lhs.names != rhs.names {return false} + if lhs._extraKeys != rhs._extraKeys {return false} + if lhs.headers != rhs.headers {return false} + if lhs.constantKeys != rhs.constantKeys {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_Lookup_V1_GrpcKeyBuilder.Name: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_Lookup_V1_GrpcKeyBuilder.protoMessageName + ".Name" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "service"), + 2: .same(proto: "method"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.service) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.method) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.service.isEmpty { + try visitor.visitSingularStringField(value: self.service, fieldNumber: 1) + } + if !self.method.isEmpty { + try visitor.visitSingularStringField(value: self.method, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_Lookup_V1_GrpcKeyBuilder.Name, rhs: Grpc_Lookup_V1_GrpcKeyBuilder.Name) -> Bool { + if lhs.service != rhs.service {return false} + if lhs.method != rhs.method {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_Lookup_V1_GrpcKeyBuilder.ExtraKeys: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_Lookup_V1_GrpcKeyBuilder.protoMessageName + ".ExtraKeys" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "host"), + 2: .same(proto: "service"), + 3: .same(proto: "method"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.host) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.service) }() + case 3: try { try decoder.decodeSingularStringField(value: &self.method) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.host.isEmpty { + try visitor.visitSingularStringField(value: self.host, fieldNumber: 1) + } + if !self.service.isEmpty { + try visitor.visitSingularStringField(value: self.service, fieldNumber: 2) + } + if !self.method.isEmpty { + try visitor.visitSingularStringField(value: self.method, fieldNumber: 3) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_Lookup_V1_GrpcKeyBuilder.ExtraKeys, rhs: Grpc_Lookup_V1_GrpcKeyBuilder.ExtraKeys) -> Bool { + if lhs.host != rhs.host {return false} + if lhs.service != rhs.service {return false} + if lhs.method != rhs.method {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_Lookup_V1_HttpKeyBuilder: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".HttpKeyBuilder" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "host_patterns"), + 2: .standard(proto: "path_patterns"), + 3: .standard(proto: "query_parameters"), + 4: .same(proto: "headers"), + 5: .standard(proto: "constant_keys"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeRepeatedStringField(value: &self.hostPatterns) }() + case 2: try { try decoder.decodeRepeatedStringField(value: &self.pathPatterns) }() + case 3: try { try decoder.decodeRepeatedMessageField(value: &self.queryParameters) }() + case 4: try { try decoder.decodeRepeatedMessageField(value: &self.headers) }() + case 5: try { try decoder.decodeMapField(fieldType: SwiftProtobuf._ProtobufMap.self, value: &self.constantKeys) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.hostPatterns.isEmpty { + try visitor.visitRepeatedStringField(value: self.hostPatterns, fieldNumber: 1) + } + if !self.pathPatterns.isEmpty { + try visitor.visitRepeatedStringField(value: self.pathPatterns, fieldNumber: 2) + } + if !self.queryParameters.isEmpty { + try visitor.visitRepeatedMessageField(value: self.queryParameters, fieldNumber: 3) + } + if !self.headers.isEmpty { + try visitor.visitRepeatedMessageField(value: self.headers, fieldNumber: 4) + } + if !self.constantKeys.isEmpty { + try visitor.visitMapField(fieldType: SwiftProtobuf._ProtobufMap.self, value: self.constantKeys, fieldNumber: 5) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_Lookup_V1_HttpKeyBuilder, rhs: Grpc_Lookup_V1_HttpKeyBuilder) -> Bool { + if lhs.hostPatterns != rhs.hostPatterns {return false} + if lhs.pathPatterns != rhs.pathPatterns {return false} + if lhs.queryParameters != rhs.queryParameters {return false} + if lhs.headers != rhs.headers {return false} + if lhs.constantKeys != rhs.constantKeys {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_Lookup_V1_RouteLookupConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".RouteLookupConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "http_keybuilders"), + 2: .standard(proto: "grpc_keybuilders"), + 3: .standard(proto: "lookup_service"), + 4: .standard(proto: "lookup_service_timeout"), + 5: .standard(proto: "max_age"), + 6: .standard(proto: "stale_age"), + 7: .standard(proto: "cache_size_bytes"), + 8: .standard(proto: "valid_targets"), + 9: .standard(proto: "default_target"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeRepeatedMessageField(value: &self.httpKeybuilders) }() + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.grpcKeybuilders) }() + case 3: try { try decoder.decodeSingularStringField(value: &self.lookupService) }() + case 4: try { try decoder.decodeSingularMessageField(value: &self._lookupServiceTimeout) }() + case 5: try { try decoder.decodeSingularMessageField(value: &self._maxAge) }() + case 6: try { try decoder.decodeSingularMessageField(value: &self._staleAge) }() + case 7: try { try decoder.decodeSingularInt64Field(value: &self.cacheSizeBytes) }() + case 8: try { try decoder.decodeRepeatedStringField(value: &self.validTargets) }() + case 9: try { try decoder.decodeSingularStringField(value: &self.defaultTarget) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if !self.httpKeybuilders.isEmpty { + try visitor.visitRepeatedMessageField(value: self.httpKeybuilders, fieldNumber: 1) + } + if !self.grpcKeybuilders.isEmpty { + try visitor.visitRepeatedMessageField(value: self.grpcKeybuilders, fieldNumber: 2) + } + if !self.lookupService.isEmpty { + try visitor.visitSingularStringField(value: self.lookupService, fieldNumber: 3) + } + try { if let v = self._lookupServiceTimeout { + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) + } }() + try { if let v = self._maxAge { + try visitor.visitSingularMessageField(value: v, fieldNumber: 5) + } }() + try { if let v = self._staleAge { + try visitor.visitSingularMessageField(value: v, fieldNumber: 6) + } }() + if self.cacheSizeBytes != 0 { + try visitor.visitSingularInt64Field(value: self.cacheSizeBytes, fieldNumber: 7) + } + if !self.validTargets.isEmpty { + try visitor.visitRepeatedStringField(value: self.validTargets, fieldNumber: 8) + } + if !self.defaultTarget.isEmpty { + try visitor.visitSingularStringField(value: self.defaultTarget, fieldNumber: 9) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_Lookup_V1_RouteLookupConfig, rhs: Grpc_Lookup_V1_RouteLookupConfig) -> Bool { + if lhs.httpKeybuilders != rhs.httpKeybuilders {return false} + if lhs.grpcKeybuilders != rhs.grpcKeybuilders {return false} + if lhs.lookupService != rhs.lookupService {return false} + if lhs._lookupServiceTimeout != rhs._lookupServiceTimeout {return false} + if lhs._maxAge != rhs._maxAge {return false} + if lhs._staleAge != rhs._staleAge {return false} + if lhs.cacheSizeBytes != rhs.cacheSizeBytes {return false} + if lhs.validTargets != rhs.validTargets {return false} + if lhs.defaultTarget != rhs.defaultTarget {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_Lookup_V1_RouteLookupClusterSpecifier: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".RouteLookupClusterSpecifier" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "route_lookup_config"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularMessageField(value: &self._routeLookupConfig) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + try { if let v = self._routeLookupConfig { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } }() + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_Lookup_V1_RouteLookupClusterSpecifier, rhs: Grpc_Lookup_V1_RouteLookupClusterSpecifier) -> Bool { + if lhs._routeLookupConfig != rhs._routeLookupConfig {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} diff --git a/Tests/GRPCCoreTests/Configuration/Generated/service_config.pb.swift b/Tests/GRPCCoreTests/Configuration/Generated/service_config.pb.swift new file mode 100644 index 000000000..8ebd3ec44 --- /dev/null +++ b/Tests/GRPCCoreTests/Configuration/Generated/service_config.pb.swift @@ -0,0 +1,4149 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: grpc/service_config/service_config.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +// Copyright 2016 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// A ServiceConfig is supplied when a service is deployed. It mostly contains +// parameters for how clients that connect to the service should behave (for +// example, the load balancing policy to use to pick between service replicas). +// +// The configuration options provided here act as overrides to automatically +// chosen option values. Service owners should be conservative in specifying +// options as the system is likely to choose better values for these options in +// the vast majority of cases. In other words, please specify a configuration +// option only if you really have to, and avoid copy-paste inclusion of configs. +// +// Note that gRPC uses the service config in JSON form, not in protobuf +// form. This proto definition is intended to help document the schema but +// will not actually be used directly by gRPC. + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +/// Configuration for a method. +struct Grpc_ServiceConfig_MethodConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var name: [Grpc_ServiceConfig_MethodConfig.Name] = [] + + /// Whether RPCs sent to this method should wait until the connection is + /// ready by default. If false, the RPC will abort immediately if there is + /// a transient failure connecting to the server. Otherwise, gRPC will + /// attempt to connect until the deadline is exceeded. + /// + /// The value specified via the gRPC client API will override the value + /// set here. However, note that setting the value in the client API will + /// also affect transient errors encountered during name resolution, which + /// cannot be caught by the value here, since the service config is + /// obtained by the gRPC client via name resolution. + var waitForReady: SwiftProtobuf.Google_Protobuf_BoolValue { + get {return _waitForReady ?? SwiftProtobuf.Google_Protobuf_BoolValue()} + set {_waitForReady = newValue} + } + /// Returns true if `waitForReady` has been explicitly set. + var hasWaitForReady: Bool {return self._waitForReady != nil} + /// Clears the value of `waitForReady`. Subsequent reads from it will return its default value. + mutating func clearWaitForReady() {self._waitForReady = nil} + + /// The default timeout in seconds for RPCs sent to this method. This can be + /// overridden in code. If no reply is received in the specified amount of + /// time, the request is aborted and a DEADLINE_EXCEEDED error status + /// is returned to the caller. + /// + /// The actual deadline used will be the minimum of the value specified here + /// and the value set by the application via the gRPC client API. If either + /// one is not set, then the other will be used. If neither is set, then the + /// request has no deadline. + var timeout: SwiftProtobuf.Google_Protobuf_Duration { + get {return _timeout ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_timeout = newValue} + } + /// Returns true if `timeout` has been explicitly set. + var hasTimeout: Bool {return self._timeout != nil} + /// Clears the value of `timeout`. Subsequent reads from it will return its default value. + mutating func clearTimeout() {self._timeout = nil} + + /// The maximum allowed payload size for an individual request or object in a + /// stream (client->server) in bytes. The size which is measured is the + /// serialized payload after per-message compression (but before stream + /// compression) in bytes. This applies both to streaming and non-streaming + /// requests. + /// + /// The actual value used is the minimum of the value specified here and the + /// value set by the application via the gRPC client API. If either one is + /// not set, then the other will be used. If neither is set, then the + /// built-in default is used. + /// + /// If a client attempts to send an object larger than this value, it will not + /// be sent and the client will see a ClientError. + /// Note that 0 is a valid value, meaning that the request message + /// must be empty. + var maxRequestMessageBytes: SwiftProtobuf.Google_Protobuf_UInt32Value { + get {return _maxRequestMessageBytes ?? SwiftProtobuf.Google_Protobuf_UInt32Value()} + set {_maxRequestMessageBytes = newValue} + } + /// Returns true if `maxRequestMessageBytes` has been explicitly set. + var hasMaxRequestMessageBytes: Bool {return self._maxRequestMessageBytes != nil} + /// Clears the value of `maxRequestMessageBytes`. Subsequent reads from it will return its default value. + mutating func clearMaxRequestMessageBytes() {self._maxRequestMessageBytes = nil} + + /// The maximum allowed payload size for an individual response or object in a + /// stream (server->client) in bytes. The size which is measured is the + /// serialized payload after per-message compression (but before stream + /// compression) in bytes. This applies both to streaming and non-streaming + /// requests. + /// + /// The actual value used is the minimum of the value specified here and the + /// value set by the application via the gRPC client API. If either one is + /// not set, then the other will be used. If neither is set, then the + /// built-in default is used. + /// + /// If a server attempts to send an object larger than this value, it will not + /// be sent, and a ServerError will be sent to the client instead. + /// Note that 0 is a valid value, meaning that the response message + /// must be empty. + var maxResponseMessageBytes: SwiftProtobuf.Google_Protobuf_UInt32Value { + get {return _maxResponseMessageBytes ?? SwiftProtobuf.Google_Protobuf_UInt32Value()} + set {_maxResponseMessageBytes = newValue} + } + /// Returns true if `maxResponseMessageBytes` has been explicitly set. + var hasMaxResponseMessageBytes: Bool {return self._maxResponseMessageBytes != nil} + /// Clears the value of `maxResponseMessageBytes`. Subsequent reads from it will return its default value. + mutating func clearMaxResponseMessageBytes() {self._maxResponseMessageBytes = nil} + + /// Only one of retry_policy or hedging_policy may be set. If neither is set, + /// RPCs will not be retried or hedged. + var retryOrHedgingPolicy: Grpc_ServiceConfig_MethodConfig.OneOf_RetryOrHedgingPolicy? = nil + + var retryPolicy: Grpc_ServiceConfig_MethodConfig.RetryPolicy { + get { + if case .retryPolicy(let v)? = retryOrHedgingPolicy {return v} + return Grpc_ServiceConfig_MethodConfig.RetryPolicy() + } + set {retryOrHedgingPolicy = .retryPolicy(newValue)} + } + + var hedgingPolicy: Grpc_ServiceConfig_MethodConfig.HedgingPolicy { + get { + if case .hedgingPolicy(let v)? = retryOrHedgingPolicy {return v} + return Grpc_ServiceConfig_MethodConfig.HedgingPolicy() + } + set {retryOrHedgingPolicy = .hedgingPolicy(newValue)} + } + + var unknownFields = SwiftProtobuf.UnknownStorage() + + /// Only one of retry_policy or hedging_policy may be set. If neither is set, + /// RPCs will not be retried or hedged. + enum OneOf_RetryOrHedgingPolicy: Equatable { + case retryPolicy(Grpc_ServiceConfig_MethodConfig.RetryPolicy) + case hedgingPolicy(Grpc_ServiceConfig_MethodConfig.HedgingPolicy) + + #if !swift(>=4.1) + static func ==(lhs: Grpc_ServiceConfig_MethodConfig.OneOf_RetryOrHedgingPolicy, rhs: Grpc_ServiceConfig_MethodConfig.OneOf_RetryOrHedgingPolicy) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.retryPolicy, .retryPolicy): return { + guard case .retryPolicy(let l) = lhs, case .retryPolicy(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.hedgingPolicy, .hedgingPolicy): return { + guard case .hedgingPolicy(let l) = lhs, case .hedgingPolicy(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif + } + + /// The names of the methods to which this configuration applies. + /// - MethodConfig without names (empty list) will be skipped. + /// - Each name entry must be unique across the entire ServiceConfig. + /// - If the 'method' field is empty, this MethodConfig specifies the defaults + /// for all methods for the specified service. + /// - If the 'service' field is empty, the 'method' field must be empty, and + /// this MethodConfig specifies the default for all methods (it's the default + /// config). + /// + /// When determining which MethodConfig to use for a given RPC, the most + /// specific match wins. For example, let's say that the service config + /// contains the following MethodConfig entries: + /// + /// method_config { name { } ... } + /// method_config { name { service: "MyService" } ... } + /// method_config { name { service: "MyService" method: "Foo" } ... } + /// + /// MyService/Foo will use the third entry, because it exactly matches the + /// service and method name. MyService/Bar will use the second entry, because + /// it provides the default for all methods of MyService. AnotherService/Baz + /// will use the first entry, because it doesn't match the other two. + /// + /// In JSON representation, value "", value `null`, and not present are the + /// same. The following are the same Name: + /// - { "service": "s" } + /// - { "service": "s", "method": null } + /// - { "service": "s", "method": "" } + struct Name { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Required. Includes proto package name. + var service: String = String() + + var method: String = String() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + } + + /// The retry policy for outgoing RPCs. + struct RetryPolicy { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// The maximum number of RPC attempts, including the original attempt. + /// + /// This field is required and must be greater than 1. + /// Any value greater than 5 will be treated as if it were 5. + var maxAttempts: UInt32 = 0 + + /// Exponential backoff parameters. The initial retry attempt will occur at + /// random(0, initial_backoff). In general, the nth attempt will occur at + /// random(0, + /// min(initial_backoff*backoff_multiplier**(n-1), max_backoff)). + /// Required. Must be greater than zero. + var initialBackoff: SwiftProtobuf.Google_Protobuf_Duration { + get {return _initialBackoff ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_initialBackoff = newValue} + } + /// Returns true if `initialBackoff` has been explicitly set. + var hasInitialBackoff: Bool {return self._initialBackoff != nil} + /// Clears the value of `initialBackoff`. Subsequent reads from it will return its default value. + mutating func clearInitialBackoff() {self._initialBackoff = nil} + + /// Required. Must be greater than zero. + var maxBackoff: SwiftProtobuf.Google_Protobuf_Duration { + get {return _maxBackoff ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_maxBackoff = newValue} + } + /// Returns true if `maxBackoff` has been explicitly set. + var hasMaxBackoff: Bool {return self._maxBackoff != nil} + /// Clears the value of `maxBackoff`. Subsequent reads from it will return its default value. + mutating func clearMaxBackoff() {self._maxBackoff = nil} + + /// Required. Must be greater than zero. + var backoffMultiplier: Float = 0 + + /// The set of status codes which may be retried. + /// + /// This field is required and must be non-empty. + var retryableStatusCodes: [Google_Rpc_Code] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _initialBackoff: SwiftProtobuf.Google_Protobuf_Duration? = nil + fileprivate var _maxBackoff: SwiftProtobuf.Google_Protobuf_Duration? = nil + } + + /// The hedging policy for outgoing RPCs. Hedged RPCs may execute more than + /// once on the server, so only idempotent methods should specify a hedging + /// policy. + struct HedgingPolicy { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// The hedging policy will send up to max_requests RPCs. + /// This number represents the total number of all attempts, including + /// the original attempt. + /// + /// This field is required and must be greater than 1. + /// Any value greater than 5 will be treated as if it were 5. + var maxAttempts: UInt32 = 0 + + /// The first RPC will be sent immediately, but the max_requests-1 subsequent + /// hedged RPCs will be sent at intervals of every hedging_delay. Set this + /// to 0 to immediately send all max_requests RPCs. + var hedgingDelay: SwiftProtobuf.Google_Protobuf_Duration { + get {return _hedgingDelay ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_hedgingDelay = newValue} + } + /// Returns true if `hedgingDelay` has been explicitly set. + var hasHedgingDelay: Bool {return self._hedgingDelay != nil} + /// Clears the value of `hedgingDelay`. Subsequent reads from it will return its default value. + mutating func clearHedgingDelay() {self._hedgingDelay = nil} + + /// The set of status codes which indicate other hedged RPCs may still + /// succeed. If a non-fatal status code is returned by the server, hedged + /// RPCs will continue. Otherwise, outstanding requests will be canceled and + /// the error returned to the client application layer. + /// + /// This field is optional. + var nonFatalStatusCodes: [Google_Rpc_Code] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _hedgingDelay: SwiftProtobuf.Google_Protobuf_Duration? = nil + } + + init() {} + + fileprivate var _waitForReady: SwiftProtobuf.Google_Protobuf_BoolValue? = nil + fileprivate var _timeout: SwiftProtobuf.Google_Protobuf_Duration? = nil + fileprivate var _maxRequestMessageBytes: SwiftProtobuf.Google_Protobuf_UInt32Value? = nil + fileprivate var _maxResponseMessageBytes: SwiftProtobuf.Google_Protobuf_UInt32Value? = nil +} + +/// Configuration for pick_first LB policy. +struct Grpc_ServiceConfig_PickFirstConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// If set to true, instructs the LB policy to randomly shuffle the list of + /// addresses received from the name resolver before attempting to connect to + /// them. + var shuffleAddressList: Bool = false + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// Configuration for round_robin LB policy. +struct Grpc_ServiceConfig_RoundRobinConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// Configuration for weighted_round_robin LB policy. +struct Grpc_ServiceConfig_WeightedRoundRobinLbConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Whether to enable out-of-band utilization reporting collection from + /// the endpoints. By default, per-request utilization reporting is used. + var enableOobLoadReport: SwiftProtobuf.Google_Protobuf_BoolValue { + get {return _enableOobLoadReport ?? SwiftProtobuf.Google_Protobuf_BoolValue()} + set {_enableOobLoadReport = newValue} + } + /// Returns true if `enableOobLoadReport` has been explicitly set. + var hasEnableOobLoadReport: Bool {return self._enableOobLoadReport != nil} + /// Clears the value of `enableOobLoadReport`. Subsequent reads from it will return its default value. + mutating func clearEnableOobLoadReport() {self._enableOobLoadReport = nil} + + /// Load reporting interval to request from the server. Note that the + /// server may not provide reports as frequently as the client requests. + /// Used only when enable_oob_load_report is true. Default is 10 seconds. + var oobReportingPeriod: SwiftProtobuf.Google_Protobuf_Duration { + get {return _oobReportingPeriod ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_oobReportingPeriod = newValue} + } + /// Returns true if `oobReportingPeriod` has been explicitly set. + var hasOobReportingPeriod: Bool {return self._oobReportingPeriod != nil} + /// Clears the value of `oobReportingPeriod`. Subsequent reads from it will return its default value. + mutating func clearOobReportingPeriod() {self._oobReportingPeriod = nil} + + /// A given endpoint must report load metrics continuously for at least + /// this long before the endpoint weight will be used. This avoids + /// churn when the set of endpoint addresses changes. Takes effect + /// both immediately after we establish a connection to an endpoint and + /// after weight_expiration_period has caused us to stop using the most + /// recent load metrics. Default is 10 seconds. + var blackoutPeriod: SwiftProtobuf.Google_Protobuf_Duration { + get {return _blackoutPeriod ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_blackoutPeriod = newValue} + } + /// Returns true if `blackoutPeriod` has been explicitly set. + var hasBlackoutPeriod: Bool {return self._blackoutPeriod != nil} + /// Clears the value of `blackoutPeriod`. Subsequent reads from it will return its default value. + mutating func clearBlackoutPeriod() {self._blackoutPeriod = nil} + + /// If a given endpoint has not reported load metrics in this long, + /// then we stop using the reported weight. This ensures that we do + /// not continue to use very stale weights. Once we stop using a stale + /// value, if we later start seeing fresh reports again, the + /// blackout_period applies. Defaults to 3 minutes. + var weightExpirationPeriod: SwiftProtobuf.Google_Protobuf_Duration { + get {return _weightExpirationPeriod ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_weightExpirationPeriod = newValue} + } + /// Returns true if `weightExpirationPeriod` has been explicitly set. + var hasWeightExpirationPeriod: Bool {return self._weightExpirationPeriod != nil} + /// Clears the value of `weightExpirationPeriod`. Subsequent reads from it will return its default value. + mutating func clearWeightExpirationPeriod() {self._weightExpirationPeriod = nil} + + /// How often endpoint weights are recalculated. Values less than 100ms are + /// capped at 100ms. Default is 1 second. + var weightUpdatePeriod: SwiftProtobuf.Google_Protobuf_Duration { + get {return _weightUpdatePeriod ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_weightUpdatePeriod = newValue} + } + /// Returns true if `weightUpdatePeriod` has been explicitly set. + var hasWeightUpdatePeriod: Bool {return self._weightUpdatePeriod != nil} + /// Clears the value of `weightUpdatePeriod`. Subsequent reads from it will return its default value. + mutating func clearWeightUpdatePeriod() {self._weightUpdatePeriod = nil} + + /// The multiplier used to adjust endpoint weights with the error rate + /// calculated as eps/qps. Configuration is rejected if this value is negative. + /// Default is 1.0. + var errorUtilizationPenalty: SwiftProtobuf.Google_Protobuf_FloatValue { + get {return _errorUtilizationPenalty ?? SwiftProtobuf.Google_Protobuf_FloatValue()} + set {_errorUtilizationPenalty = newValue} + } + /// Returns true if `errorUtilizationPenalty` has been explicitly set. + var hasErrorUtilizationPenalty: Bool {return self._errorUtilizationPenalty != nil} + /// Clears the value of `errorUtilizationPenalty`. Subsequent reads from it will return its default value. + mutating func clearErrorUtilizationPenalty() {self._errorUtilizationPenalty = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _enableOobLoadReport: SwiftProtobuf.Google_Protobuf_BoolValue? = nil + fileprivate var _oobReportingPeriod: SwiftProtobuf.Google_Protobuf_Duration? = nil + fileprivate var _blackoutPeriod: SwiftProtobuf.Google_Protobuf_Duration? = nil + fileprivate var _weightExpirationPeriod: SwiftProtobuf.Google_Protobuf_Duration? = nil + fileprivate var _weightUpdatePeriod: SwiftProtobuf.Google_Protobuf_Duration? = nil + fileprivate var _errorUtilizationPenalty: SwiftProtobuf.Google_Protobuf_FloatValue? = nil +} + +/// Configuration for outlier_detection LB policy +struct Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// The time interval between ejection analysis sweeps. This can result in + /// both new ejections as well as addresses being returned to service. Defaults + /// to 10000ms or 10s. + var interval: SwiftProtobuf.Google_Protobuf_Duration { + get {return _interval ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_interval = newValue} + } + /// Returns true if `interval` has been explicitly set. + var hasInterval: Bool {return self._interval != nil} + /// Clears the value of `interval`. Subsequent reads from it will return its default value. + mutating func clearInterval() {self._interval = nil} + + /// The base time that as address is ejected for. The real time is equal to the + /// base time multiplied by the number of times the address has been ejected. + /// Defaults to 30000ms or 30s. + var baseEjectionTime: SwiftProtobuf.Google_Protobuf_Duration { + get {return _baseEjectionTime ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_baseEjectionTime = newValue} + } + /// Returns true if `baseEjectionTime` has been explicitly set. + var hasBaseEjectionTime: Bool {return self._baseEjectionTime != nil} + /// Clears the value of `baseEjectionTime`. Subsequent reads from it will return its default value. + mutating func clearBaseEjectionTime() {self._baseEjectionTime = nil} + + /// The maximum time that an address is ejected for. If not specified, the default value (300000ms or 300s) or + /// the base_ejection_time value is applied, whatever is larger. + var maxEjectionTime: SwiftProtobuf.Google_Protobuf_Duration { + get {return _maxEjectionTime ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_maxEjectionTime = newValue} + } + /// Returns true if `maxEjectionTime` has been explicitly set. + var hasMaxEjectionTime: Bool {return self._maxEjectionTime != nil} + /// Clears the value of `maxEjectionTime`. Subsequent reads from it will return its default value. + mutating func clearMaxEjectionTime() {self._maxEjectionTime = nil} + + /// The maximum % of an address list that can be ejected due to outlier + /// detection. Defaults to 10% but will eject at least one address regardless of the value. + var maxEjectionPercent: SwiftProtobuf.Google_Protobuf_UInt32Value { + get {return _maxEjectionPercent ?? SwiftProtobuf.Google_Protobuf_UInt32Value()} + set {_maxEjectionPercent = newValue} + } + /// Returns true if `maxEjectionPercent` has been explicitly set. + var hasMaxEjectionPercent: Bool {return self._maxEjectionPercent != nil} + /// Clears the value of `maxEjectionPercent`. Subsequent reads from it will return its default value. + mutating func clearMaxEjectionPercent() {self._maxEjectionPercent = nil} + + /// If set, success rate ejections will be performed + var successRateEjection: Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.SuccessRateEjection { + get {return _successRateEjection ?? Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.SuccessRateEjection()} + set {_successRateEjection = newValue} + } + /// Returns true if `successRateEjection` has been explicitly set. + var hasSuccessRateEjection: Bool {return self._successRateEjection != nil} + /// Clears the value of `successRateEjection`. Subsequent reads from it will return its default value. + mutating func clearSuccessRateEjection() {self._successRateEjection = nil} + + /// If set, failure rate ejections will be performed + var failurePercentageEjection: Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.FailurePercentageEjection { + get {return _failurePercentageEjection ?? Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.FailurePercentageEjection()} + set {_failurePercentageEjection = newValue} + } + /// Returns true if `failurePercentageEjection` has been explicitly set. + var hasFailurePercentageEjection: Bool {return self._failurePercentageEjection != nil} + /// Clears the value of `failurePercentageEjection`. Subsequent reads from it will return its default value. + mutating func clearFailurePercentageEjection() {self._failurePercentageEjection = nil} + + /// The config for the child policy + var childPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + /// Parameters for the success rate ejection algorithm. + /// This algorithm monitors the request success rate for all endpoints and + /// ejects individual endpoints whose success rates are statistical outliers. + struct SuccessRateEjection { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// This factor is used to determine the ejection threshold for success rate + /// outlier ejection. The ejection threshold is the difference between the + /// mean success rate, and the product of this factor and the standard + /// deviation of the mean success rate: mean - (stdev * + /// success_rate_stdev_factor). This factor is divided by a thousand to get a + /// double. That is, if the desired factor is 1.9, the runtime value should + /// be 1900. Defaults to 1900. + var stdevFactor: SwiftProtobuf.Google_Protobuf_UInt32Value { + get {return _stdevFactor ?? SwiftProtobuf.Google_Protobuf_UInt32Value()} + set {_stdevFactor = newValue} + } + /// Returns true if `stdevFactor` has been explicitly set. + var hasStdevFactor: Bool {return self._stdevFactor != nil} + /// Clears the value of `stdevFactor`. Subsequent reads from it will return its default value. + mutating func clearStdevFactor() {self._stdevFactor = nil} + + /// The % chance that an address will be actually ejected when an outlier status + /// is detected through success rate statistics. This setting can be used to + /// disable ejection or to ramp it up slowly. Defaults to 100. + var enforcementPercentage: SwiftProtobuf.Google_Protobuf_UInt32Value { + get {return _enforcementPercentage ?? SwiftProtobuf.Google_Protobuf_UInt32Value()} + set {_enforcementPercentage = newValue} + } + /// Returns true if `enforcementPercentage` has been explicitly set. + var hasEnforcementPercentage: Bool {return self._enforcementPercentage != nil} + /// Clears the value of `enforcementPercentage`. Subsequent reads from it will return its default value. + mutating func clearEnforcementPercentage() {self._enforcementPercentage = nil} + + /// The number of addresses that must have enough request volume to + /// detect success rate outliers. If the number of addresses is less than this + /// setting, outlier detection via success rate statistics is not performed + /// for any addresses. Defaults to 5. + var minimumHosts: SwiftProtobuf.Google_Protobuf_UInt32Value { + get {return _minimumHosts ?? SwiftProtobuf.Google_Protobuf_UInt32Value()} + set {_minimumHosts = newValue} + } + /// Returns true if `minimumHosts` has been explicitly set. + var hasMinimumHosts: Bool {return self._minimumHosts != nil} + /// Clears the value of `minimumHosts`. Subsequent reads from it will return its default value. + mutating func clearMinimumHosts() {self._minimumHosts = nil} + + /// The minimum number of total requests that must be collected in one + /// interval (as defined by the interval duration above) to include this address + /// in success rate based outlier detection. If the volume is lower than this + /// setting, outlier detection via success rate statistics is not performed + /// for that address. Defaults to 100. + var requestVolume: SwiftProtobuf.Google_Protobuf_UInt32Value { + get {return _requestVolume ?? SwiftProtobuf.Google_Protobuf_UInt32Value()} + set {_requestVolume = newValue} + } + /// Returns true if `requestVolume` has been explicitly set. + var hasRequestVolume: Bool {return self._requestVolume != nil} + /// Clears the value of `requestVolume`. Subsequent reads from it will return its default value. + mutating func clearRequestVolume() {self._requestVolume = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _stdevFactor: SwiftProtobuf.Google_Protobuf_UInt32Value? = nil + fileprivate var _enforcementPercentage: SwiftProtobuf.Google_Protobuf_UInt32Value? = nil + fileprivate var _minimumHosts: SwiftProtobuf.Google_Protobuf_UInt32Value? = nil + fileprivate var _requestVolume: SwiftProtobuf.Google_Protobuf_UInt32Value? = nil + } + + /// Parameters for the failure percentage algorithm. + /// This algorithm ejects individual endpoints whose failure rate is greater than + /// some threshold, independently of any other endpoint. + struct FailurePercentageEjection { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// The failure percentage to use when determining failure percentage-based outlier detection. If + /// the failure percentage of a given address is greater than or equal to this value, it will be + /// ejected. Defaults to 85. + var threshold: SwiftProtobuf.Google_Protobuf_UInt32Value { + get {return _threshold ?? SwiftProtobuf.Google_Protobuf_UInt32Value()} + set {_threshold = newValue} + } + /// Returns true if `threshold` has been explicitly set. + var hasThreshold: Bool {return self._threshold != nil} + /// Clears the value of `threshold`. Subsequent reads from it will return its default value. + mutating func clearThreshold() {self._threshold = nil} + + /// The % chance that an address will be actually ejected when an outlier status is detected through + /// failure percentage statistics. This setting can be used to disable ejection or to ramp it up + /// slowly. Defaults to 100. + var enforcementPercentage: SwiftProtobuf.Google_Protobuf_UInt32Value { + get {return _enforcementPercentage ?? SwiftProtobuf.Google_Protobuf_UInt32Value()} + set {_enforcementPercentage = newValue} + } + /// Returns true if `enforcementPercentage` has been explicitly set. + var hasEnforcementPercentage: Bool {return self._enforcementPercentage != nil} + /// Clears the value of `enforcementPercentage`. Subsequent reads from it will return its default value. + mutating func clearEnforcementPercentage() {self._enforcementPercentage = nil} + + /// The minimum number of addresses in order to perform failure percentage-based ejection. + /// If the total number of addresses is less than this value, failure percentage-based + /// ejection will not be performed. Defaults to 5. + var minimumHosts: SwiftProtobuf.Google_Protobuf_UInt32Value { + get {return _minimumHosts ?? SwiftProtobuf.Google_Protobuf_UInt32Value()} + set {_minimumHosts = newValue} + } + /// Returns true if `minimumHosts` has been explicitly set. + var hasMinimumHosts: Bool {return self._minimumHosts != nil} + /// Clears the value of `minimumHosts`. Subsequent reads from it will return its default value. + mutating func clearMinimumHosts() {self._minimumHosts = nil} + + /// The minimum number of total requests that must be collected in one interval (as defined by the + /// interval duration above) to perform failure percentage-based ejection for this address. If the + /// volume is lower than this setting, failure percentage-based ejection will not be performed for + /// this host. Defaults to 50. + var requestVolume: SwiftProtobuf.Google_Protobuf_UInt32Value { + get {return _requestVolume ?? SwiftProtobuf.Google_Protobuf_UInt32Value()} + set {_requestVolume = newValue} + } + /// Returns true if `requestVolume` has been explicitly set. + var hasRequestVolume: Bool {return self._requestVolume != nil} + /// Clears the value of `requestVolume`. Subsequent reads from it will return its default value. + mutating func clearRequestVolume() {self._requestVolume = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _threshold: SwiftProtobuf.Google_Protobuf_UInt32Value? = nil + fileprivate var _enforcementPercentage: SwiftProtobuf.Google_Protobuf_UInt32Value? = nil + fileprivate var _minimumHosts: SwiftProtobuf.Google_Protobuf_UInt32Value? = nil + fileprivate var _requestVolume: SwiftProtobuf.Google_Protobuf_UInt32Value? = nil + } + + init() {} + + fileprivate var _interval: SwiftProtobuf.Google_Protobuf_Duration? = nil + fileprivate var _baseEjectionTime: SwiftProtobuf.Google_Protobuf_Duration? = nil + fileprivate var _maxEjectionTime: SwiftProtobuf.Google_Protobuf_Duration? = nil + fileprivate var _maxEjectionPercent: SwiftProtobuf.Google_Protobuf_UInt32Value? = nil + fileprivate var _successRateEjection: Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.SuccessRateEjection? = nil + fileprivate var _failurePercentageEjection: Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.FailurePercentageEjection? = nil +} + +/// Configuration for grpclb LB policy. +struct Grpc_ServiceConfig_GrpcLbConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Optional. What LB policy to use for routing between the backend + /// addresses. If unset, defaults to round_robin. + /// Currently, the only supported values are round_robin and pick_first. + /// Note that this will be used both in balancer mode and in fallback mode. + /// Multiple LB policies can be specified; clients will iterate through + /// the list in order and stop at the first policy that they support. + var childPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + /// Optional. If specified, overrides the name of the service to be sent to + /// the balancer. + var serviceName: String = String() + + /// Optional. The timeout in seconds for receiving the server list from the LB + /// server. Defaults to 10s. + var initialFallbackTimeout: SwiftProtobuf.Google_Protobuf_Duration { + get {return _initialFallbackTimeout ?? SwiftProtobuf.Google_Protobuf_Duration()} + set {_initialFallbackTimeout = newValue} + } + /// Returns true if `initialFallbackTimeout` has been explicitly set. + var hasInitialFallbackTimeout: Bool {return self._initialFallbackTimeout != nil} + /// Clears the value of `initialFallbackTimeout`. Subsequent reads from it will return its default value. + mutating func clearInitialFallbackTimeout() {self._initialFallbackTimeout = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _initialFallbackTimeout: SwiftProtobuf.Google_Protobuf_Duration? = nil +} + +/// Configuration for priority LB policy. +struct Grpc_ServiceConfig_PriorityLoadBalancingPolicyConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var children: Dictionary = [:] + + /// A list of child names in decreasing priority order + /// (i.e., first element is the highest priority). + var priorities: [String] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + /// A map of name to child policy configuration. + /// The names are used to allow the priority policy to update + /// existing child policies instead of creating new ones every + /// time it receives a config update. + struct Child { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var config: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + /// If true, will ignore reresolution requests from this child. + var ignoreReresolutionRequests: Bool = false + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + } + + init() {} +} + +/// Configuration for weighted_target LB policy. +struct Grpc_ServiceConfig_WeightedTargetLoadBalancingPolicyConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var targets: Dictionary = [:] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + struct Target { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var weight: UInt32 = 0 + + var childPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + } + + init() {} +} + +/// Config for RLS LB policy. +struct Grpc_ServiceConfig_RlsLoadBalancingPolicyConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var routeLookupConfig: Grpc_Lookup_V1_RouteLookupConfig { + get {return _storage._routeLookupConfig ?? Grpc_Lookup_V1_RouteLookupConfig()} + set {_uniqueStorage()._routeLookupConfig = newValue} + } + /// Returns true if `routeLookupConfig` has been explicitly set. + var hasRouteLookupConfig: Bool {return _storage._routeLookupConfig != nil} + /// Clears the value of `routeLookupConfig`. Subsequent reads from it will return its default value. + mutating func clearRouteLookupConfig() {_uniqueStorage()._routeLookupConfig = nil} + + /// Service config to use for the RLS channel. + var routeLookupChannelServiceConfig: Grpc_ServiceConfig_ServiceConfig { + get {return _storage._routeLookupChannelServiceConfig ?? Grpc_ServiceConfig_ServiceConfig()} + set {_uniqueStorage()._routeLookupChannelServiceConfig = newValue} + } + /// Returns true if `routeLookupChannelServiceConfig` has been explicitly set. + var hasRouteLookupChannelServiceConfig: Bool {return _storage._routeLookupChannelServiceConfig != nil} + /// Clears the value of `routeLookupChannelServiceConfig`. Subsequent reads from it will return its default value. + mutating func clearRouteLookupChannelServiceConfig() {_uniqueStorage()._routeLookupChannelServiceConfig = nil} + + var childPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] { + get {return _storage._childPolicy} + set {_uniqueStorage()._childPolicy = newValue} + } + + /// Field name to add to child policy config to contain the target name. + var childPolicyConfigTargetFieldName: String { + get {return _storage._childPolicyConfigTargetFieldName} + set {_uniqueStorage()._childPolicyConfigTargetFieldName = newValue} + } + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _storage = _StorageClass.defaultInstance +} + +/// Configuration for xds_cluster_manager_experimental LB policy. +struct Grpc_ServiceConfig_XdsClusterManagerLoadBalancingPolicyConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var children: Dictionary = [:] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + struct Child { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var childPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + } + + init() {} +} + +/// Configuration for the cds LB policy. +struct Grpc_ServiceConfig_CdsConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Required. + var cluster: String = String() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// Represents an xDS server. +struct Grpc_ServiceConfig_XdsServer { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Required. + var serverUri: String = String() + + /// A list of channel creds to use. The first supported type will be used. + var channelCreds: [Grpc_ServiceConfig_XdsServer.ChannelCredentials] = [] + + /// A repeated list of server features. + var serverFeatures: [SwiftProtobuf.Google_Protobuf_Value] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + struct ChannelCredentials { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Required. + var type: String = String() + + /// Optional JSON config. + var config: SwiftProtobuf.Google_Protobuf_Struct { + get {return _config ?? SwiftProtobuf.Google_Protobuf_Struct()} + set {_config = newValue} + } + /// Returns true if `config` has been explicitly set. + var hasConfig: Bool {return self._config != nil} + /// Clears the value of `config`. Subsequent reads from it will return its default value. + mutating func clearConfig() {self._config = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _config: SwiftProtobuf.Google_Protobuf_Struct? = nil + } + + init() {} +} + +/// Configuration for xds_cluster_resolver LB policy. +struct Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Ordered list of discovery mechanisms. + /// Must have at least one element. + /// Results from each discovery mechanism are concatenated together in + /// successive priorities. + var discoveryMechanisms: [Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig.DiscoveryMechanism] = [] + + /// xDS LB policy. Will be used as the child config of the xds_cluster_impl LB policy. + var xdsLbPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + /// Describes a discovery mechanism instance. + /// For EDS or LOGICAL_DNS clusters, there will be exactly one + /// DiscoveryMechanism, which will describe the cluster of the parent + /// CDS policy. + /// For aggregate clusters, there will be one DiscoveryMechanism for each + /// underlying cluster. + struct DiscoveryMechanism { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Cluster name. + var cluster: String { + get {return _storage._cluster} + set {_uniqueStorage()._cluster = newValue} + } + + /// LRS server to send load reports to. + /// If not present, load reporting will be disabled. + /// If set to the empty string, load reporting will be sent to the same + /// server that we obtained CDS data from. + /// DEPRECATED: Use new lrs_load_reporting_server field instead. + var lrsLoadReportingServerName: SwiftProtobuf.Google_Protobuf_StringValue { + get {return _storage._lrsLoadReportingServerName ?? SwiftProtobuf.Google_Protobuf_StringValue()} + set {_uniqueStorage()._lrsLoadReportingServerName = newValue} + } + /// Returns true if `lrsLoadReportingServerName` has been explicitly set. + var hasLrsLoadReportingServerName: Bool {return _storage._lrsLoadReportingServerName != nil} + /// Clears the value of `lrsLoadReportingServerName`. Subsequent reads from it will return its default value. + mutating func clearLrsLoadReportingServerName() {_uniqueStorage()._lrsLoadReportingServerName = nil} + + /// LRS server to send load reports to. + /// If not present, load reporting will be disabled. + /// Supercedes lrs_load_reporting_server_name field. + var lrsLoadReportingServer: Grpc_ServiceConfig_XdsServer { + get {return _storage._lrsLoadReportingServer ?? Grpc_ServiceConfig_XdsServer()} + set {_uniqueStorage()._lrsLoadReportingServer = newValue} + } + /// Returns true if `lrsLoadReportingServer` has been explicitly set. + var hasLrsLoadReportingServer: Bool {return _storage._lrsLoadReportingServer != nil} + /// Clears the value of `lrsLoadReportingServer`. Subsequent reads from it will return its default value. + mutating func clearLrsLoadReportingServer() {_uniqueStorage()._lrsLoadReportingServer = nil} + + /// Maximum number of outstanding requests can be made to the upstream + /// cluster. Default is 1024. + var maxConcurrentRequests: SwiftProtobuf.Google_Protobuf_UInt32Value { + get {return _storage._maxConcurrentRequests ?? SwiftProtobuf.Google_Protobuf_UInt32Value()} + set {_uniqueStorage()._maxConcurrentRequests = newValue} + } + /// Returns true if `maxConcurrentRequests` has been explicitly set. + var hasMaxConcurrentRequests: Bool {return _storage._maxConcurrentRequests != nil} + /// Clears the value of `maxConcurrentRequests`. Subsequent reads from it will return its default value. + mutating func clearMaxConcurrentRequests() {_uniqueStorage()._maxConcurrentRequests = nil} + + var type: Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig.DiscoveryMechanism.TypeEnum { + get {return _storage._type} + set {_uniqueStorage()._type = newValue} + } + + /// For type EDS only. + /// EDS service name, as returned in CDS. + /// May be unset if not specified in CDS. + var edsServiceName: String { + get {return _storage._edsServiceName} + set {_uniqueStorage()._edsServiceName = newValue} + } + + /// For type LOGICAL_DNS only. + /// DNS name to resolve in "host:port" form. + var dnsHostname: String { + get {return _storage._dnsHostname} + set {_uniqueStorage()._dnsHostname = newValue} + } + + /// The configuration for outlier_detection child policies + /// Within this message, the child_policy field will be ignored + var outlierDetection: Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig { + get {return _storage._outlierDetection ?? Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig()} + set {_uniqueStorage()._outlierDetection = newValue} + } + /// Returns true if `outlierDetection` has been explicitly set. + var hasOutlierDetection: Bool {return _storage._outlierDetection != nil} + /// Clears the value of `outlierDetection`. Subsequent reads from it will return its default value. + mutating func clearOutlierDetection() {_uniqueStorage()._outlierDetection = nil} + + /// The configuration for xds_override_host child policy + var overrideHostStatus: [Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig.HealthStatus] { + get {return _storage._overrideHostStatus} + set {_uniqueStorage()._overrideHostStatus = newValue} + } + + /// Telemetry labels associated with this cluster + var telemetryLabels: Dictionary { + get {return _storage._telemetryLabels} + set {_uniqueStorage()._telemetryLabels = newValue} + } + + var unknownFields = SwiftProtobuf.UnknownStorage() + + enum TypeEnum: SwiftProtobuf.Enum { + typealias RawValue = Int + case unknown // = 0 + case eds // = 1 + case logicalDns // = 2 + case UNRECOGNIZED(Int) + + init() { + self = .unknown + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .unknown + case 1: self = .eds + case 2: self = .logicalDns + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .unknown: return 0 + case .eds: return 1 + case .logicalDns: return 2 + case .UNRECOGNIZED(let i): return i + } + } + + } + + init() {} + + fileprivate var _storage = _StorageClass.defaultInstance + } + + init() {} +} + +#if swift(>=4.2) + +extension Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig.DiscoveryMechanism.TypeEnum: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static let allCases: [Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig.DiscoveryMechanism.TypeEnum] = [ + .unknown, + .eds, + .logicalDns, + ] +} + +#endif // swift(>=4.2) + +/// Configuration for xds_cluster_impl LB policy. +struct Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Cluster name. Required. + var cluster: String = String() + + /// EDS service name. + /// Not set if cluster is not an EDS cluster or if it does not + /// specify an EDS service name. + var edsServiceName: String = String() + + /// Server to send load reports to. + /// If unset, no load reporting is done. + /// If set to empty string, load reporting will be sent to the same + /// server as we are getting xds data from. + /// DEPRECATED: Use new lrs_load_reporting_server field instead. + var lrsLoadReportingServerName: SwiftProtobuf.Google_Protobuf_StringValue { + get {return _lrsLoadReportingServerName ?? SwiftProtobuf.Google_Protobuf_StringValue()} + set {_lrsLoadReportingServerName = newValue} + } + /// Returns true if `lrsLoadReportingServerName` has been explicitly set. + var hasLrsLoadReportingServerName: Bool {return self._lrsLoadReportingServerName != nil} + /// Clears the value of `lrsLoadReportingServerName`. Subsequent reads from it will return its default value. + mutating func clearLrsLoadReportingServerName() {self._lrsLoadReportingServerName = nil} + + /// LRS server to send load reports to. + /// If not present, load reporting will be disabled. + /// Supercedes lrs_load_reporting_server_name field. + var lrsLoadReportingServer: Grpc_ServiceConfig_XdsServer { + get {return _lrsLoadReportingServer ?? Grpc_ServiceConfig_XdsServer()} + set {_lrsLoadReportingServer = newValue} + } + /// Returns true if `lrsLoadReportingServer` has been explicitly set. + var hasLrsLoadReportingServer: Bool {return self._lrsLoadReportingServer != nil} + /// Clears the value of `lrsLoadReportingServer`. Subsequent reads from it will return its default value. + mutating func clearLrsLoadReportingServer() {self._lrsLoadReportingServer = nil} + + /// Maximum number of outstanding requests can be made to the upstream cluster. + /// Default is 1024. + var maxConcurrentRequests: SwiftProtobuf.Google_Protobuf_UInt32Value { + get {return _maxConcurrentRequests ?? SwiftProtobuf.Google_Protobuf_UInt32Value()} + set {_maxConcurrentRequests = newValue} + } + /// Returns true if `maxConcurrentRequests` has been explicitly set. + var hasMaxConcurrentRequests: Bool {return self._maxConcurrentRequests != nil} + /// Clears the value of `maxConcurrentRequests`. Subsequent reads from it will return its default value. + mutating func clearMaxConcurrentRequests() {self._maxConcurrentRequests = nil} + + var dropCategories: [Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig.DropCategory] = [] + + /// Child policy. + var childPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + /// Telemetry labels associated with this cluster + var telemetryLabels: Dictionary = [:] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + /// Drop configuration. + struct DropCategory { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var category: String = String() + + var requestsPerMillion: UInt32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + } + + init() {} + + fileprivate var _lrsLoadReportingServerName: SwiftProtobuf.Google_Protobuf_StringValue? = nil + fileprivate var _lrsLoadReportingServer: Grpc_ServiceConfig_XdsServer? = nil + fileprivate var _maxConcurrentRequests: SwiftProtobuf.Google_Protobuf_UInt32Value? = nil +} + +/// Configuration for eds LB policy. +struct Grpc_ServiceConfig_EdsLoadBalancingPolicyConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Cluster name. Required. + var cluster: String = String() + + /// EDS service name, as returned in CDS. + /// May be unset if not specified in CDS. + var edsServiceName: String = String() + + /// Server to send load reports to. + /// If unset, no load reporting is done. + /// If set to empty string, load reporting will be sent to the same + /// server as we are getting xds data from. + var lrsLoadReportingServerName: SwiftProtobuf.Google_Protobuf_StringValue { + get {return _lrsLoadReportingServerName ?? SwiftProtobuf.Google_Protobuf_StringValue()} + set {_lrsLoadReportingServerName = newValue} + } + /// Returns true if `lrsLoadReportingServerName` has been explicitly set. + var hasLrsLoadReportingServerName: Bool {return self._lrsLoadReportingServerName != nil} + /// Clears the value of `lrsLoadReportingServerName`. Subsequent reads from it will return its default value. + mutating func clearLrsLoadReportingServerName() {self._lrsLoadReportingServerName = nil} + + /// Locality-picking policy. + /// This policy's config is expected to be in the format used + /// by the weighted_target policy. Note that the config should include + /// an empty value for the "targets" field; that empty value will be + /// replaced by one that is dynamically generated based on the EDS data. + /// Optional; defaults to "weighted_target". + var localityPickingPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + /// Endpoint-picking policy. + /// This will be configured as the policy for each child in the + /// locality-policy's config. + /// Optional; defaults to "round_robin". + var endpointPickingPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _lrsLoadReportingServerName: SwiftProtobuf.Google_Protobuf_StringValue? = nil +} + +/// Configuration for ring_hash LB policy. +struct Grpc_ServiceConfig_RingHashLoadBalancingConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// A client-side option will cap these values to 4096. If either of these + /// values are greater than the client-side cap, they will be treated + /// as the client-side cap value. + var minRingSize: UInt64 = 0 + + /// Optional, defaults to 4096, max 8M. + var maxRingSize: UInt64 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// Configuration for lrs LB policy. +struct Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Cluster name. Required. + var clusterName: String = String() + + /// EDS service name, as returned in CDS. + /// May be unset if not specified in CDS. + var edsServiceName: String = String() + + /// Server to send load reports to. Required. + /// If set to empty string, load reporting will be sent to the same + /// server as we are getting xds data from. + var lrsLoadReportingServerName: String = String() + + var locality: Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig.Locality { + get {return _locality ?? Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig.Locality()} + set {_locality = newValue} + } + /// Returns true if `locality` has been explicitly set. + var hasLocality: Bool {return self._locality != nil} + /// Clears the value of `locality`. Subsequent reads from it will return its default value. + mutating func clearLocality() {self._locality = nil} + + /// Endpoint-picking policy. + var childPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + /// The locality for which this policy will report load. Required. + struct Locality { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var region: String = String() + + var zone: String = String() + + var subzone: String = String() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + } + + init() {} + + fileprivate var _locality: Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig.Locality? = nil +} + +/// Configuration for the xds_wrr_locality load balancing policy. +struct Grpc_ServiceConfig_XdsWrrLocalityLoadBalancingPolicyConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var childPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// Configuration for the least_request LB policy. +struct Grpc_ServiceConfig_LeastRequestLocalityLoadBalancingPolicyConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var choiceCount: UInt64 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// Configuration for the override_host LB policy. +struct Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// valid health status for hosts that are considered when using + /// xds_override_host_experimental policy. + /// Default is [UNKNOWN, HEALTHY] + var overrideHostStatus: [Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig.HealthStatus] = [] + + var childPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + enum HealthStatus: SwiftProtobuf.Enum { + typealias RawValue = Int + case unknown // = 0 + case healthy // = 1 + case draining // = 3 + case UNRECOGNIZED(Int) + + init() { + self = .unknown + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .unknown + case 1: self = .healthy + case 3: self = .draining + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .unknown: return 0 + case .healthy: return 1 + case .draining: return 3 + case .UNRECOGNIZED(let i): return i + } + } + + } + + init() {} +} + +#if swift(>=4.2) + +extension Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig.HealthStatus: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static let allCases: [Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig.HealthStatus] = [ + .unknown, + .healthy, + .draining, + ] +} + +#endif // swift(>=4.2) + +/// Configuration for xds LB policy. +struct Grpc_ServiceConfig_XdsConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Name of balancer to connect to. + var balancerName: String = String() + + /// Optional. What LB policy to use for intra-locality routing. + /// If unset, will use whatever algorithm is specified by the balancer. + /// Multiple LB policies can be specified; clients will iterate through + /// the list in order and stop at the first policy that they support. + var childPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + /// Optional. What LB policy to use in fallback mode. If not + /// specified, defaults to round_robin. + /// Multiple LB policies can be specified; clients will iterate through + /// the list in order and stop at the first policy that they support. + var fallbackPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + /// Optional. Name to use in EDS query. If not present, defaults to + /// the server name from the target URI. + var edsServiceName: String = String() + + /// LRS server to send load reports to. + /// If not present, load reporting will be disabled. + /// If set to the empty string, load reporting will be sent to the same + /// server that we obtained CDS data from. + var lrsLoadReportingServerName: SwiftProtobuf.Google_Protobuf_StringValue { + get {return _lrsLoadReportingServerName ?? SwiftProtobuf.Google_Protobuf_StringValue()} + set {_lrsLoadReportingServerName = newValue} + } + /// Returns true if `lrsLoadReportingServerName` has been explicitly set. + var hasLrsLoadReportingServerName: Bool {return self._lrsLoadReportingServerName != nil} + /// Clears the value of `lrsLoadReportingServerName`. Subsequent reads from it will return its default value. + mutating func clearLrsLoadReportingServerName() {self._lrsLoadReportingServerName = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _lrsLoadReportingServerName: SwiftProtobuf.Google_Protobuf_StringValue? = nil +} + +/// Selects LB policy and provides corresponding configuration. +/// +/// In general, all instances of this field should be repeated. Clients will +/// iterate through the list in order and stop at the first policy that they +/// support. This allows the service config to specify custom policies that may +/// not be known to all clients. +/// +/// - If the config for the first supported policy is invalid, the whole service +/// config is invalid. +/// - If the list doesn't contain any supported policy, the whole service config +/// is invalid. +struct Grpc_ServiceConfig_LoadBalancingConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Exactly one LB policy may be configured. + var policy: Grpc_ServiceConfig_LoadBalancingConfig.OneOf_Policy? = nil + + var pickFirst: Grpc_ServiceConfig_PickFirstConfig { + get { + if case .pickFirst(let v)? = policy {return v} + return Grpc_ServiceConfig_PickFirstConfig() + } + set {policy = .pickFirst(newValue)} + } + + var roundRobin: Grpc_ServiceConfig_RoundRobinConfig { + get { + if case .roundRobin(let v)? = policy {return v} + return Grpc_ServiceConfig_RoundRobinConfig() + } + set {policy = .roundRobin(newValue)} + } + + var weightedRoundRobin: Grpc_ServiceConfig_WeightedRoundRobinLbConfig { + get { + if case .weightedRoundRobin(let v)? = policy {return v} + return Grpc_ServiceConfig_WeightedRoundRobinLbConfig() + } + set {policy = .weightedRoundRobin(newValue)} + } + + /// gRPC lookaside load balancing. + /// This will eventually be deprecated by the new xDS-based local + /// balancing policy. + var grpclb: Grpc_ServiceConfig_GrpcLbConfig { + get { + if case .grpclb(let v)? = policy {return v} + return Grpc_ServiceConfig_GrpcLbConfig() + } + set {policy = .grpclb(newValue)} + } + + var priorityExperimental: Grpc_ServiceConfig_PriorityLoadBalancingPolicyConfig { + get { + if case .priorityExperimental(let v)? = policy {return v} + return Grpc_ServiceConfig_PriorityLoadBalancingPolicyConfig() + } + set {policy = .priorityExperimental(newValue)} + } + + var weightedTargetExperimental: Grpc_ServiceConfig_WeightedTargetLoadBalancingPolicyConfig { + get { + if case .weightedTargetExperimental(let v)? = policy {return v} + return Grpc_ServiceConfig_WeightedTargetLoadBalancingPolicyConfig() + } + set {policy = .weightedTargetExperimental(newValue)} + } + + var outlierDetection: Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig { + get { + if case .outlierDetection(let v)? = policy {return v} + return Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig() + } + set {policy = .outlierDetection(newValue)} + } + + var rls: Grpc_ServiceConfig_RlsLoadBalancingPolicyConfig { + get { + if case .rls(let v)? = policy {return v} + return Grpc_ServiceConfig_RlsLoadBalancingPolicyConfig() + } + set {policy = .rls(newValue)} + } + + /// xDS-based load balancing. + var xdsClusterManagerExperimental: Grpc_ServiceConfig_XdsClusterManagerLoadBalancingPolicyConfig { + get { + if case .xdsClusterManagerExperimental(let v)? = policy {return v} + return Grpc_ServiceConfig_XdsClusterManagerLoadBalancingPolicyConfig() + } + set {policy = .xdsClusterManagerExperimental(newValue)} + } + + var cdsExperimental: Grpc_ServiceConfig_CdsConfig { + get { + if case .cdsExperimental(let v)? = policy {return v} + return Grpc_ServiceConfig_CdsConfig() + } + set {policy = .cdsExperimental(newValue)} + } + + var xdsClusterResolverExperimental: Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig { + get { + if case .xdsClusterResolverExperimental(let v)? = policy {return v} + return Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig() + } + set {policy = .xdsClusterResolverExperimental(newValue)} + } + + var xdsClusterImplExperimental: Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig { + get { + if case .xdsClusterImplExperimental(let v)? = policy {return v} + return Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig() + } + set {policy = .xdsClusterImplExperimental(newValue)} + } + + var overrideHostExperimental: Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig { + get { + if case .overrideHostExperimental(let v)? = policy {return v} + return Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig() + } + set {policy = .overrideHostExperimental(newValue)} + } + + var xdsWrrLocalityExperimental: Grpc_ServiceConfig_XdsWrrLocalityLoadBalancingPolicyConfig { + get { + if case .xdsWrrLocalityExperimental(let v)? = policy {return v} + return Grpc_ServiceConfig_XdsWrrLocalityLoadBalancingPolicyConfig() + } + set {policy = .xdsWrrLocalityExperimental(newValue)} + } + + var ringHashExperimental: Grpc_ServiceConfig_RingHashLoadBalancingConfig { + get { + if case .ringHashExperimental(let v)? = policy {return v} + return Grpc_ServiceConfig_RingHashLoadBalancingConfig() + } + set {policy = .ringHashExperimental(newValue)} + } + + var leastRequestExperimental: Grpc_ServiceConfig_LeastRequestLocalityLoadBalancingPolicyConfig { + get { + if case .leastRequestExperimental(let v)? = policy {return v} + return Grpc_ServiceConfig_LeastRequestLocalityLoadBalancingPolicyConfig() + } + set {policy = .leastRequestExperimental(newValue)} + } + + /// Deprecated xDS-related policies. + var lrsExperimental: Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig { + get { + if case .lrsExperimental(let v)? = policy {return v} + return Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig() + } + set {policy = .lrsExperimental(newValue)} + } + + var edsExperimental: Grpc_ServiceConfig_EdsLoadBalancingPolicyConfig { + get { + if case .edsExperimental(let v)? = policy {return v} + return Grpc_ServiceConfig_EdsLoadBalancingPolicyConfig() + } + set {policy = .edsExperimental(newValue)} + } + + var xds: Grpc_ServiceConfig_XdsConfig { + get { + if case .xds(let v)? = policy {return v} + return Grpc_ServiceConfig_XdsConfig() + } + set {policy = .xds(newValue)} + } + + var xdsExperimental: Grpc_ServiceConfig_XdsConfig { + get { + if case .xdsExperimental(let v)? = policy {return v} + return Grpc_ServiceConfig_XdsConfig() + } + set {policy = .xdsExperimental(newValue)} + } + + var unknownFields = SwiftProtobuf.UnknownStorage() + + /// Exactly one LB policy may be configured. + enum OneOf_Policy: Equatable { + case pickFirst(Grpc_ServiceConfig_PickFirstConfig) + case roundRobin(Grpc_ServiceConfig_RoundRobinConfig) + case weightedRoundRobin(Grpc_ServiceConfig_WeightedRoundRobinLbConfig) + /// gRPC lookaside load balancing. + /// This will eventually be deprecated by the new xDS-based local + /// balancing policy. + case grpclb(Grpc_ServiceConfig_GrpcLbConfig) + case priorityExperimental(Grpc_ServiceConfig_PriorityLoadBalancingPolicyConfig) + case weightedTargetExperimental(Grpc_ServiceConfig_WeightedTargetLoadBalancingPolicyConfig) + case outlierDetection(Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig) + case rls(Grpc_ServiceConfig_RlsLoadBalancingPolicyConfig) + /// xDS-based load balancing. + case xdsClusterManagerExperimental(Grpc_ServiceConfig_XdsClusterManagerLoadBalancingPolicyConfig) + case cdsExperimental(Grpc_ServiceConfig_CdsConfig) + case xdsClusterResolverExperimental(Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig) + case xdsClusterImplExperimental(Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig) + case overrideHostExperimental(Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig) + case xdsWrrLocalityExperimental(Grpc_ServiceConfig_XdsWrrLocalityLoadBalancingPolicyConfig) + case ringHashExperimental(Grpc_ServiceConfig_RingHashLoadBalancingConfig) + case leastRequestExperimental(Grpc_ServiceConfig_LeastRequestLocalityLoadBalancingPolicyConfig) + /// Deprecated xDS-related policies. + case lrsExperimental(Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig) + case edsExperimental(Grpc_ServiceConfig_EdsLoadBalancingPolicyConfig) + case xds(Grpc_ServiceConfig_XdsConfig) + case xdsExperimental(Grpc_ServiceConfig_XdsConfig) + + #if !swift(>=4.1) + static func ==(lhs: Grpc_ServiceConfig_LoadBalancingConfig.OneOf_Policy, rhs: Grpc_ServiceConfig_LoadBalancingConfig.OneOf_Policy) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.pickFirst, .pickFirst): return { + guard case .pickFirst(let l) = lhs, case .pickFirst(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.roundRobin, .roundRobin): return { + guard case .roundRobin(let l) = lhs, case .roundRobin(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.weightedRoundRobin, .weightedRoundRobin): return { + guard case .weightedRoundRobin(let l) = lhs, case .weightedRoundRobin(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.grpclb, .grpclb): return { + guard case .grpclb(let l) = lhs, case .grpclb(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.priorityExperimental, .priorityExperimental): return { + guard case .priorityExperimental(let l) = lhs, case .priorityExperimental(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.weightedTargetExperimental, .weightedTargetExperimental): return { + guard case .weightedTargetExperimental(let l) = lhs, case .weightedTargetExperimental(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.outlierDetection, .outlierDetection): return { + guard case .outlierDetection(let l) = lhs, case .outlierDetection(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.rls, .rls): return { + guard case .rls(let l) = lhs, case .rls(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.xdsClusterManagerExperimental, .xdsClusterManagerExperimental): return { + guard case .xdsClusterManagerExperimental(let l) = lhs, case .xdsClusterManagerExperimental(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.cdsExperimental, .cdsExperimental): return { + guard case .cdsExperimental(let l) = lhs, case .cdsExperimental(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.xdsClusterResolverExperimental, .xdsClusterResolverExperimental): return { + guard case .xdsClusterResolverExperimental(let l) = lhs, case .xdsClusterResolverExperimental(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.xdsClusterImplExperimental, .xdsClusterImplExperimental): return { + guard case .xdsClusterImplExperimental(let l) = lhs, case .xdsClusterImplExperimental(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.overrideHostExperimental, .overrideHostExperimental): return { + guard case .overrideHostExperimental(let l) = lhs, case .overrideHostExperimental(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.xdsWrrLocalityExperimental, .xdsWrrLocalityExperimental): return { + guard case .xdsWrrLocalityExperimental(let l) = lhs, case .xdsWrrLocalityExperimental(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.ringHashExperimental, .ringHashExperimental): return { + guard case .ringHashExperimental(let l) = lhs, case .ringHashExperimental(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.leastRequestExperimental, .leastRequestExperimental): return { + guard case .leastRequestExperimental(let l) = lhs, case .leastRequestExperimental(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.lrsExperimental, .lrsExperimental): return { + guard case .lrsExperimental(let l) = lhs, case .lrsExperimental(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.edsExperimental, .edsExperimental): return { + guard case .edsExperimental(let l) = lhs, case .edsExperimental(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.xds, .xds): return { + guard case .xds(let l) = lhs, case .xds(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.xdsExperimental, .xdsExperimental): return { + guard case .xdsExperimental(let l) = lhs, case .xdsExperimental(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif + } + + init() {} +} + +/// A ServiceConfig represents information about a service but is not specific to +/// any name resolver. +struct Grpc_ServiceConfig_ServiceConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var loadBalancingPolicy: Grpc_ServiceConfig_ServiceConfig.LoadBalancingPolicy = .unspecified + + /// Multiple LB policies can be specified; clients will iterate through + /// the list in order and stop at the first policy that they support. If none + /// are supported, the service config is considered invalid. + var loadBalancingConfig: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + + /// Per-method configuration. + var methodConfig: [Grpc_ServiceConfig_MethodConfig] = [] + + var retryThrottling: Grpc_ServiceConfig_ServiceConfig.RetryThrottlingPolicy { + get {return _retryThrottling ?? Grpc_ServiceConfig_ServiceConfig.RetryThrottlingPolicy()} + set {_retryThrottling = newValue} + } + /// Returns true if `retryThrottling` has been explicitly set. + var hasRetryThrottling: Bool {return self._retryThrottling != nil} + /// Clears the value of `retryThrottling`. Subsequent reads from it will return its default value. + mutating func clearRetryThrottling() {self._retryThrottling = nil} + + var healthCheckConfig: Grpc_ServiceConfig_ServiceConfig.HealthCheckConfig { + get {return _healthCheckConfig ?? Grpc_ServiceConfig_ServiceConfig.HealthCheckConfig()} + set {_healthCheckConfig = newValue} + } + /// Returns true if `healthCheckConfig` has been explicitly set. + var hasHealthCheckConfig: Bool {return self._healthCheckConfig != nil} + /// Clears the value of `healthCheckConfig`. Subsequent reads from it will return its default value. + mutating func clearHealthCheckConfig() {self._healthCheckConfig = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + /// Load balancing policy. + /// + /// Note that load_balancing_policy is deprecated in favor of + /// load_balancing_config; the former will be used only if the latter + /// is unset. + /// + /// If no LB policy is configured here, then the default is pick_first. + /// If the policy name is set via the client API, that value overrides + /// the value specified here. + /// + /// If the deprecated load_balancing_policy field is used, note that if the + /// resolver returns at least one balancer address (as opposed to backend + /// addresses), gRPC will use grpclb (see + /// https://github.com/grpc/grpc/blob/master/doc/load-balancing.md), + /// regardless of what policy is configured here. However, if the resolver + /// returns at least one backend address in addition to the balancer + /// address(es), the client may fall back to the requested policy if it + /// is unable to reach any of the grpclb load balancers. + enum LoadBalancingPolicy: SwiftProtobuf.Enum { + typealias RawValue = Int + case unspecified // = 0 + case roundRobin // = 1 + case UNRECOGNIZED(Int) + + init() { + self = .unspecified + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .unspecified + case 1: self = .roundRobin + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .unspecified: return 0 + case .roundRobin: return 1 + case .UNRECOGNIZED(let i): return i + } + } + + } + + /// If a RetryThrottlingPolicy is provided, gRPC will automatically throttle + /// retry attempts and hedged RPCs when the client's ratio of failures to + /// successes exceeds a threshold. + /// + /// For each server name, the gRPC client will maintain a token_count which is + /// initially set to max_tokens. Every outgoing RPC (regardless of service or + /// method invoked) will change token_count as follows: + /// + /// - Every failed RPC will decrement the token_count by 1. + /// - Every successful RPC will increment the token_count by token_ratio. + /// + /// If token_count is less than or equal to max_tokens / 2, then RPCs will not + /// be retried and hedged RPCs will not be sent. + struct RetryThrottlingPolicy { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// The number of tokens starts at max_tokens. The token_count will always be + /// between 0 and max_tokens. + /// + /// This field is required and must be greater than zero. + var maxTokens: UInt32 = 0 + + /// The amount of tokens to add on each successful RPC. Typically this will + /// be some number between 0 and 1, e.g., 0.1. + /// + /// This field is required and must be greater than zero. Up to 3 decimal + /// places are supported. + var tokenRatio: Float = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + } + + struct HealthCheckConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Service name to use in the health-checking request. + var serviceName: SwiftProtobuf.Google_Protobuf_StringValue { + get {return _serviceName ?? SwiftProtobuf.Google_Protobuf_StringValue()} + set {_serviceName = newValue} + } + /// Returns true if `serviceName` has been explicitly set. + var hasServiceName: Bool {return self._serviceName != nil} + /// Clears the value of `serviceName`. Subsequent reads from it will return its default value. + mutating func clearServiceName() {self._serviceName = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _serviceName: SwiftProtobuf.Google_Protobuf_StringValue? = nil + } + + init() {} + + fileprivate var _retryThrottling: Grpc_ServiceConfig_ServiceConfig.RetryThrottlingPolicy? = nil + fileprivate var _healthCheckConfig: Grpc_ServiceConfig_ServiceConfig.HealthCheckConfig? = nil +} + +#if swift(>=4.2) + +extension Grpc_ServiceConfig_ServiceConfig.LoadBalancingPolicy: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static let allCases: [Grpc_ServiceConfig_ServiceConfig.LoadBalancingPolicy] = [ + .unspecified, + .roundRobin, + ] +} + +#endif // swift(>=4.2) + +#if swift(>=5.5) && canImport(_Concurrency) +extension Grpc_ServiceConfig_MethodConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_MethodConfig.OneOf_RetryOrHedgingPolicy: @unchecked Sendable {} +extension Grpc_ServiceConfig_MethodConfig.Name: @unchecked Sendable {} +extension Grpc_ServiceConfig_MethodConfig.RetryPolicy: @unchecked Sendable {} +extension Grpc_ServiceConfig_MethodConfig.HedgingPolicy: @unchecked Sendable {} +extension Grpc_ServiceConfig_PickFirstConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_RoundRobinConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_WeightedRoundRobinLbConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.SuccessRateEjection: @unchecked Sendable {} +extension Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.FailurePercentageEjection: @unchecked Sendable {} +extension Grpc_ServiceConfig_GrpcLbConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_PriorityLoadBalancingPolicyConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_PriorityLoadBalancingPolicyConfig.Child: @unchecked Sendable {} +extension Grpc_ServiceConfig_WeightedTargetLoadBalancingPolicyConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_WeightedTargetLoadBalancingPolicyConfig.Target: @unchecked Sendable {} +extension Grpc_ServiceConfig_RlsLoadBalancingPolicyConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_XdsClusterManagerLoadBalancingPolicyConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_XdsClusterManagerLoadBalancingPolicyConfig.Child: @unchecked Sendable {} +extension Grpc_ServiceConfig_CdsConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_XdsServer: @unchecked Sendable {} +extension Grpc_ServiceConfig_XdsServer.ChannelCredentials: @unchecked Sendable {} +extension Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig.DiscoveryMechanism: @unchecked Sendable {} +extension Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig.DiscoveryMechanism.TypeEnum: @unchecked Sendable {} +extension Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig.DropCategory: @unchecked Sendable {} +extension Grpc_ServiceConfig_EdsLoadBalancingPolicyConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_RingHashLoadBalancingConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig.Locality: @unchecked Sendable {} +extension Grpc_ServiceConfig_XdsWrrLocalityLoadBalancingPolicyConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_LeastRequestLocalityLoadBalancingPolicyConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig.HealthStatus: @unchecked Sendable {} +extension Grpc_ServiceConfig_XdsConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_LoadBalancingConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_LoadBalancingConfig.OneOf_Policy: @unchecked Sendable {} +extension Grpc_ServiceConfig_ServiceConfig: @unchecked Sendable {} +extension Grpc_ServiceConfig_ServiceConfig.LoadBalancingPolicy: @unchecked Sendable {} +extension Grpc_ServiceConfig_ServiceConfig.RetryThrottlingPolicy: @unchecked Sendable {} +extension Grpc_ServiceConfig_ServiceConfig.HealthCheckConfig: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +fileprivate let _protobuf_package = "grpc.service_config" + +extension Grpc_ServiceConfig_MethodConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".MethodConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "name"), + 2: .standard(proto: "wait_for_ready"), + 3: .same(proto: "timeout"), + 4: .standard(proto: "max_request_message_bytes"), + 5: .standard(proto: "max_response_message_bytes"), + 6: .standard(proto: "retry_policy"), + 7: .standard(proto: "hedging_policy"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeRepeatedMessageField(value: &self.name) }() + case 2: try { try decoder.decodeSingularMessageField(value: &self._waitForReady) }() + case 3: try { try decoder.decodeSingularMessageField(value: &self._timeout) }() + case 4: try { try decoder.decodeSingularMessageField(value: &self._maxRequestMessageBytes) }() + case 5: try { try decoder.decodeSingularMessageField(value: &self._maxResponseMessageBytes) }() + case 6: try { + var v: Grpc_ServiceConfig_MethodConfig.RetryPolicy? + var hadOneofValue = false + if let current = self.retryOrHedgingPolicy { + hadOneofValue = true + if case .retryPolicy(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.retryOrHedgingPolicy = .retryPolicy(v) + } + }() + case 7: try { + var v: Grpc_ServiceConfig_MethodConfig.HedgingPolicy? + var hadOneofValue = false + if let current = self.retryOrHedgingPolicy { + hadOneofValue = true + if case .hedgingPolicy(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.retryOrHedgingPolicy = .hedgingPolicy(v) + } + }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if !self.name.isEmpty { + try visitor.visitRepeatedMessageField(value: self.name, fieldNumber: 1) + } + try { if let v = self._waitForReady { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } }() + try { if let v = self._timeout { + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + } }() + try { if let v = self._maxRequestMessageBytes { + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) + } }() + try { if let v = self._maxResponseMessageBytes { + try visitor.visitSingularMessageField(value: v, fieldNumber: 5) + } }() + switch self.retryOrHedgingPolicy { + case .retryPolicy?: try { + guard case .retryPolicy(let v)? = self.retryOrHedgingPolicy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 6) + }() + case .hedgingPolicy?: try { + guard case .hedgingPolicy(let v)? = self.retryOrHedgingPolicy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 7) + }() + case nil: break + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_MethodConfig, rhs: Grpc_ServiceConfig_MethodConfig) -> Bool { + if lhs.name != rhs.name {return false} + if lhs._waitForReady != rhs._waitForReady {return false} + if lhs._timeout != rhs._timeout {return false} + if lhs._maxRequestMessageBytes != rhs._maxRequestMessageBytes {return false} + if lhs._maxResponseMessageBytes != rhs._maxResponseMessageBytes {return false} + if lhs.retryOrHedgingPolicy != rhs.retryOrHedgingPolicy {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_MethodConfig.Name: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_ServiceConfig_MethodConfig.protoMessageName + ".Name" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "service"), + 2: .same(proto: "method"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.service) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.method) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.service.isEmpty { + try visitor.visitSingularStringField(value: self.service, fieldNumber: 1) + } + if !self.method.isEmpty { + try visitor.visitSingularStringField(value: self.method, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_MethodConfig.Name, rhs: Grpc_ServiceConfig_MethodConfig.Name) -> Bool { + if lhs.service != rhs.service {return false} + if lhs.method != rhs.method {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_MethodConfig.RetryPolicy: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_ServiceConfig_MethodConfig.protoMessageName + ".RetryPolicy" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "max_attempts"), + 2: .standard(proto: "initial_backoff"), + 3: .standard(proto: "max_backoff"), + 4: .standard(proto: "backoff_multiplier"), + 5: .standard(proto: "retryable_status_codes"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularUInt32Field(value: &self.maxAttempts) }() + case 2: try { try decoder.decodeSingularMessageField(value: &self._initialBackoff) }() + case 3: try { try decoder.decodeSingularMessageField(value: &self._maxBackoff) }() + case 4: try { try decoder.decodeSingularFloatField(value: &self.backoffMultiplier) }() + case 5: try { try decoder.decodeRepeatedEnumField(value: &self.retryableStatusCodes) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if self.maxAttempts != 0 { + try visitor.visitSingularUInt32Field(value: self.maxAttempts, fieldNumber: 1) + } + try { if let v = self._initialBackoff { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } }() + try { if let v = self._maxBackoff { + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + } }() + if self.backoffMultiplier != 0 { + try visitor.visitSingularFloatField(value: self.backoffMultiplier, fieldNumber: 4) + } + if !self.retryableStatusCodes.isEmpty { + try visitor.visitPackedEnumField(value: self.retryableStatusCodes, fieldNumber: 5) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_MethodConfig.RetryPolicy, rhs: Grpc_ServiceConfig_MethodConfig.RetryPolicy) -> Bool { + if lhs.maxAttempts != rhs.maxAttempts {return false} + if lhs._initialBackoff != rhs._initialBackoff {return false} + if lhs._maxBackoff != rhs._maxBackoff {return false} + if lhs.backoffMultiplier != rhs.backoffMultiplier {return false} + if lhs.retryableStatusCodes != rhs.retryableStatusCodes {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_MethodConfig.HedgingPolicy: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_ServiceConfig_MethodConfig.protoMessageName + ".HedgingPolicy" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "max_attempts"), + 2: .standard(proto: "hedging_delay"), + 3: .standard(proto: "non_fatal_status_codes"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularUInt32Field(value: &self.maxAttempts) }() + case 2: try { try decoder.decodeSingularMessageField(value: &self._hedgingDelay) }() + case 3: try { try decoder.decodeRepeatedEnumField(value: &self.nonFatalStatusCodes) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if self.maxAttempts != 0 { + try visitor.visitSingularUInt32Field(value: self.maxAttempts, fieldNumber: 1) + } + try { if let v = self._hedgingDelay { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } }() + if !self.nonFatalStatusCodes.isEmpty { + try visitor.visitPackedEnumField(value: self.nonFatalStatusCodes, fieldNumber: 3) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_MethodConfig.HedgingPolicy, rhs: Grpc_ServiceConfig_MethodConfig.HedgingPolicy) -> Bool { + if lhs.maxAttempts != rhs.maxAttempts {return false} + if lhs._hedgingDelay != rhs._hedgingDelay {return false} + if lhs.nonFatalStatusCodes != rhs.nonFatalStatusCodes {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_PickFirstConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".PickFirstConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "shuffle_address_list"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularBoolField(value: &self.shuffleAddressList) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.shuffleAddressList != false { + try visitor.visitSingularBoolField(value: self.shuffleAddressList, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_PickFirstConfig, rhs: Grpc_ServiceConfig_PickFirstConfig) -> Bool { + if lhs.shuffleAddressList != rhs.shuffleAddressList {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_RoundRobinConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".RoundRobinConfig" + static let _protobuf_nameMap = SwiftProtobuf._NameMap() + + mutating func decodeMessage(decoder: inout D) throws { + while let _ = try decoder.nextFieldNumber() { + } + } + + func traverse(visitor: inout V) throws { + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_RoundRobinConfig, rhs: Grpc_ServiceConfig_RoundRobinConfig) -> Bool { + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_WeightedRoundRobinLbConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".WeightedRoundRobinLbConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "enable_oob_load_report"), + 2: .standard(proto: "oob_reporting_period"), + 3: .standard(proto: "blackout_period"), + 4: .standard(proto: "weight_expiration_period"), + 5: .standard(proto: "weight_update_period"), + 6: .standard(proto: "error_utilization_penalty"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularMessageField(value: &self._enableOobLoadReport) }() + case 2: try { try decoder.decodeSingularMessageField(value: &self._oobReportingPeriod) }() + case 3: try { try decoder.decodeSingularMessageField(value: &self._blackoutPeriod) }() + case 4: try { try decoder.decodeSingularMessageField(value: &self._weightExpirationPeriod) }() + case 5: try { try decoder.decodeSingularMessageField(value: &self._weightUpdatePeriod) }() + case 6: try { try decoder.decodeSingularMessageField(value: &self._errorUtilizationPenalty) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + try { if let v = self._enableOobLoadReport { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } }() + try { if let v = self._oobReportingPeriod { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } }() + try { if let v = self._blackoutPeriod { + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + } }() + try { if let v = self._weightExpirationPeriod { + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) + } }() + try { if let v = self._weightUpdatePeriod { + try visitor.visitSingularMessageField(value: v, fieldNumber: 5) + } }() + try { if let v = self._errorUtilizationPenalty { + try visitor.visitSingularMessageField(value: v, fieldNumber: 6) + } }() + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_WeightedRoundRobinLbConfig, rhs: Grpc_ServiceConfig_WeightedRoundRobinLbConfig) -> Bool { + if lhs._enableOobLoadReport != rhs._enableOobLoadReport {return false} + if lhs._oobReportingPeriod != rhs._oobReportingPeriod {return false} + if lhs._blackoutPeriod != rhs._blackoutPeriod {return false} + if lhs._weightExpirationPeriod != rhs._weightExpirationPeriod {return false} + if lhs._weightUpdatePeriod != rhs._weightUpdatePeriod {return false} + if lhs._errorUtilizationPenalty != rhs._errorUtilizationPenalty {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".OutlierDetectionLoadBalancingConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "interval"), + 2: .standard(proto: "base_ejection_time"), + 3: .standard(proto: "max_ejection_time"), + 4: .standard(proto: "max_ejection_percent"), + 5: .standard(proto: "success_rate_ejection"), + 6: .standard(proto: "failure_percentage_ejection"), + 13: .standard(proto: "child_policy"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularMessageField(value: &self._interval) }() + case 2: try { try decoder.decodeSingularMessageField(value: &self._baseEjectionTime) }() + case 3: try { try decoder.decodeSingularMessageField(value: &self._maxEjectionTime) }() + case 4: try { try decoder.decodeSingularMessageField(value: &self._maxEjectionPercent) }() + case 5: try { try decoder.decodeSingularMessageField(value: &self._successRateEjection) }() + case 6: try { try decoder.decodeSingularMessageField(value: &self._failurePercentageEjection) }() + case 13: try { try decoder.decodeRepeatedMessageField(value: &self.childPolicy) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + try { if let v = self._interval { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } }() + try { if let v = self._baseEjectionTime { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } }() + try { if let v = self._maxEjectionTime { + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + } }() + try { if let v = self._maxEjectionPercent { + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) + } }() + try { if let v = self._successRateEjection { + try visitor.visitSingularMessageField(value: v, fieldNumber: 5) + } }() + try { if let v = self._failurePercentageEjection { + try visitor.visitSingularMessageField(value: v, fieldNumber: 6) + } }() + if !self.childPolicy.isEmpty { + try visitor.visitRepeatedMessageField(value: self.childPolicy, fieldNumber: 13) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig, rhs: Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig) -> Bool { + if lhs._interval != rhs._interval {return false} + if lhs._baseEjectionTime != rhs._baseEjectionTime {return false} + if lhs._maxEjectionTime != rhs._maxEjectionTime {return false} + if lhs._maxEjectionPercent != rhs._maxEjectionPercent {return false} + if lhs._successRateEjection != rhs._successRateEjection {return false} + if lhs._failurePercentageEjection != rhs._failurePercentageEjection {return false} + if lhs.childPolicy != rhs.childPolicy {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.SuccessRateEjection: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.protoMessageName + ".SuccessRateEjection" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "stdev_factor"), + 2: .standard(proto: "enforcement_percentage"), + 3: .standard(proto: "minimum_hosts"), + 4: .standard(proto: "request_volume"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularMessageField(value: &self._stdevFactor) }() + case 2: try { try decoder.decodeSingularMessageField(value: &self._enforcementPercentage) }() + case 3: try { try decoder.decodeSingularMessageField(value: &self._minimumHosts) }() + case 4: try { try decoder.decodeSingularMessageField(value: &self._requestVolume) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + try { if let v = self._stdevFactor { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } }() + try { if let v = self._enforcementPercentage { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } }() + try { if let v = self._minimumHosts { + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + } }() + try { if let v = self._requestVolume { + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) + } }() + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.SuccessRateEjection, rhs: Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.SuccessRateEjection) -> Bool { + if lhs._stdevFactor != rhs._stdevFactor {return false} + if lhs._enforcementPercentage != rhs._enforcementPercentage {return false} + if lhs._minimumHosts != rhs._minimumHosts {return false} + if lhs._requestVolume != rhs._requestVolume {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.FailurePercentageEjection: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.protoMessageName + ".FailurePercentageEjection" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "threshold"), + 2: .standard(proto: "enforcement_percentage"), + 3: .standard(proto: "minimum_hosts"), + 4: .standard(proto: "request_volume"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularMessageField(value: &self._threshold) }() + case 2: try { try decoder.decodeSingularMessageField(value: &self._enforcementPercentage) }() + case 3: try { try decoder.decodeSingularMessageField(value: &self._minimumHosts) }() + case 4: try { try decoder.decodeSingularMessageField(value: &self._requestVolume) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + try { if let v = self._threshold { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } }() + try { if let v = self._enforcementPercentage { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } }() + try { if let v = self._minimumHosts { + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + } }() + try { if let v = self._requestVolume { + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) + } }() + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.FailurePercentageEjection, rhs: Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig.FailurePercentageEjection) -> Bool { + if lhs._threshold != rhs._threshold {return false} + if lhs._enforcementPercentage != rhs._enforcementPercentage {return false} + if lhs._minimumHosts != rhs._minimumHosts {return false} + if lhs._requestVolume != rhs._requestVolume {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_GrpcLbConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".GrpcLbConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "child_policy"), + 2: .standard(proto: "service_name"), + 3: .standard(proto: "initial_fallback_timeout"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeRepeatedMessageField(value: &self.childPolicy) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.serviceName) }() + case 3: try { try decoder.decodeSingularMessageField(value: &self._initialFallbackTimeout) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if !self.childPolicy.isEmpty { + try visitor.visitRepeatedMessageField(value: self.childPolicy, fieldNumber: 1) + } + if !self.serviceName.isEmpty { + try visitor.visitSingularStringField(value: self.serviceName, fieldNumber: 2) + } + try { if let v = self._initialFallbackTimeout { + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + } }() + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_GrpcLbConfig, rhs: Grpc_ServiceConfig_GrpcLbConfig) -> Bool { + if lhs.childPolicy != rhs.childPolicy {return false} + if lhs.serviceName != rhs.serviceName {return false} + if lhs._initialFallbackTimeout != rhs._initialFallbackTimeout {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_PriorityLoadBalancingPolicyConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".PriorityLoadBalancingPolicyConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "children"), + 2: .same(proto: "priorities"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeMapField(fieldType: SwiftProtobuf._ProtobufMessageMap.self, value: &self.children) }() + case 2: try { try decoder.decodeRepeatedStringField(value: &self.priorities) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.children.isEmpty { + try visitor.visitMapField(fieldType: SwiftProtobuf._ProtobufMessageMap.self, value: self.children, fieldNumber: 1) + } + if !self.priorities.isEmpty { + try visitor.visitRepeatedStringField(value: self.priorities, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_PriorityLoadBalancingPolicyConfig, rhs: Grpc_ServiceConfig_PriorityLoadBalancingPolicyConfig) -> Bool { + if lhs.children != rhs.children {return false} + if lhs.priorities != rhs.priorities {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_PriorityLoadBalancingPolicyConfig.Child: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_ServiceConfig_PriorityLoadBalancingPolicyConfig.protoMessageName + ".Child" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "config"), + 2: .standard(proto: "ignore_reresolution_requests"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeRepeatedMessageField(value: &self.config) }() + case 2: try { try decoder.decodeSingularBoolField(value: &self.ignoreReresolutionRequests) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.config.isEmpty { + try visitor.visitRepeatedMessageField(value: self.config, fieldNumber: 1) + } + if self.ignoreReresolutionRequests != false { + try visitor.visitSingularBoolField(value: self.ignoreReresolutionRequests, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_PriorityLoadBalancingPolicyConfig.Child, rhs: Grpc_ServiceConfig_PriorityLoadBalancingPolicyConfig.Child) -> Bool { + if lhs.config != rhs.config {return false} + if lhs.ignoreReresolutionRequests != rhs.ignoreReresolutionRequests {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_WeightedTargetLoadBalancingPolicyConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".WeightedTargetLoadBalancingPolicyConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "targets"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeMapField(fieldType: SwiftProtobuf._ProtobufMessageMap.self, value: &self.targets) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.targets.isEmpty { + try visitor.visitMapField(fieldType: SwiftProtobuf._ProtobufMessageMap.self, value: self.targets, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_WeightedTargetLoadBalancingPolicyConfig, rhs: Grpc_ServiceConfig_WeightedTargetLoadBalancingPolicyConfig) -> Bool { + if lhs.targets != rhs.targets {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_WeightedTargetLoadBalancingPolicyConfig.Target: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_ServiceConfig_WeightedTargetLoadBalancingPolicyConfig.protoMessageName + ".Target" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "weight"), + 2: .standard(proto: "child_policy"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularUInt32Field(value: &self.weight) }() + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.childPolicy) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.weight != 0 { + try visitor.visitSingularUInt32Field(value: self.weight, fieldNumber: 1) + } + if !self.childPolicy.isEmpty { + try visitor.visitRepeatedMessageField(value: self.childPolicy, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_WeightedTargetLoadBalancingPolicyConfig.Target, rhs: Grpc_ServiceConfig_WeightedTargetLoadBalancingPolicyConfig.Target) -> Bool { + if lhs.weight != rhs.weight {return false} + if lhs.childPolicy != rhs.childPolicy {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_RlsLoadBalancingPolicyConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".RlsLoadBalancingPolicyConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "route_lookup_config"), + 2: .standard(proto: "route_lookup_channel_service_config"), + 3: .standard(proto: "child_policy"), + 4: .standard(proto: "child_policy_config_target_field_name"), + ] + + fileprivate class _StorageClass { + var _routeLookupConfig: Grpc_Lookup_V1_RouteLookupConfig? = nil + var _routeLookupChannelServiceConfig: Grpc_ServiceConfig_ServiceConfig? = nil + var _childPolicy: [Grpc_ServiceConfig_LoadBalancingConfig] = [] + var _childPolicyConfigTargetFieldName: String = String() + + static let defaultInstance = _StorageClass() + + private init() {} + + init(copying source: _StorageClass) { + _routeLookupConfig = source._routeLookupConfig + _routeLookupChannelServiceConfig = source._routeLookupChannelServiceConfig + _childPolicy = source._childPolicy + _childPolicyConfigTargetFieldName = source._childPolicyConfigTargetFieldName + } + } + + fileprivate mutating func _uniqueStorage() -> _StorageClass { + if !isKnownUniquelyReferenced(&_storage) { + _storage = _StorageClass(copying: _storage) + } + return _storage + } + + mutating func decodeMessage(decoder: inout D) throws { + _ = _uniqueStorage() + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularMessageField(value: &_storage._routeLookupConfig) }() + case 2: try { try decoder.decodeSingularMessageField(value: &_storage._routeLookupChannelServiceConfig) }() + case 3: try { try decoder.decodeRepeatedMessageField(value: &_storage._childPolicy) }() + case 4: try { try decoder.decodeSingularStringField(value: &_storage._childPolicyConfigTargetFieldName) }() + default: break + } + } + } + } + + func traverse(visitor: inout V) throws { + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + try { if let v = _storage._routeLookupConfig { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } }() + try { if let v = _storage._routeLookupChannelServiceConfig { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } }() + if !_storage._childPolicy.isEmpty { + try visitor.visitRepeatedMessageField(value: _storage._childPolicy, fieldNumber: 3) + } + if !_storage._childPolicyConfigTargetFieldName.isEmpty { + try visitor.visitSingularStringField(value: _storage._childPolicyConfigTargetFieldName, fieldNumber: 4) + } + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_RlsLoadBalancingPolicyConfig, rhs: Grpc_ServiceConfig_RlsLoadBalancingPolicyConfig) -> Bool { + if lhs._storage !== rhs._storage { + let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in + let _storage = _args.0 + let rhs_storage = _args.1 + if _storage._routeLookupConfig != rhs_storage._routeLookupConfig {return false} + if _storage._routeLookupChannelServiceConfig != rhs_storage._routeLookupChannelServiceConfig {return false} + if _storage._childPolicy != rhs_storage._childPolicy {return false} + if _storage._childPolicyConfigTargetFieldName != rhs_storage._childPolicyConfigTargetFieldName {return false} + return true + } + if !storagesAreEqual {return false} + } + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_XdsClusterManagerLoadBalancingPolicyConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".XdsClusterManagerLoadBalancingPolicyConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "children"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeMapField(fieldType: SwiftProtobuf._ProtobufMessageMap.self, value: &self.children) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.children.isEmpty { + try visitor.visitMapField(fieldType: SwiftProtobuf._ProtobufMessageMap.self, value: self.children, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_XdsClusterManagerLoadBalancingPolicyConfig, rhs: Grpc_ServiceConfig_XdsClusterManagerLoadBalancingPolicyConfig) -> Bool { + if lhs.children != rhs.children {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_XdsClusterManagerLoadBalancingPolicyConfig.Child: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_ServiceConfig_XdsClusterManagerLoadBalancingPolicyConfig.protoMessageName + ".Child" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "child_policy"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeRepeatedMessageField(value: &self.childPolicy) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.childPolicy.isEmpty { + try visitor.visitRepeatedMessageField(value: self.childPolicy, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_XdsClusterManagerLoadBalancingPolicyConfig.Child, rhs: Grpc_ServiceConfig_XdsClusterManagerLoadBalancingPolicyConfig.Child) -> Bool { + if lhs.childPolicy != rhs.childPolicy {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_CdsConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".CdsConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "cluster"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.cluster) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.cluster.isEmpty { + try visitor.visitSingularStringField(value: self.cluster, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_CdsConfig, rhs: Grpc_ServiceConfig_CdsConfig) -> Bool { + if lhs.cluster != rhs.cluster {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_XdsServer: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".XdsServer" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "server_uri"), + 2: .same(proto: "channel_creds"), + 3: .same(proto: "server_features"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.serverUri) }() + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.channelCreds) }() + case 3: try { try decoder.decodeRepeatedMessageField(value: &self.serverFeatures) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.serverUri.isEmpty { + try visitor.visitSingularStringField(value: self.serverUri, fieldNumber: 1) + } + if !self.channelCreds.isEmpty { + try visitor.visitRepeatedMessageField(value: self.channelCreds, fieldNumber: 2) + } + if !self.serverFeatures.isEmpty { + try visitor.visitRepeatedMessageField(value: self.serverFeatures, fieldNumber: 3) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_XdsServer, rhs: Grpc_ServiceConfig_XdsServer) -> Bool { + if lhs.serverUri != rhs.serverUri {return false} + if lhs.channelCreds != rhs.channelCreds {return false} + if lhs.serverFeatures != rhs.serverFeatures {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_XdsServer.ChannelCredentials: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_ServiceConfig_XdsServer.protoMessageName + ".ChannelCredentials" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "type"), + 2: .same(proto: "config"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.type) }() + case 2: try { try decoder.decodeSingularMessageField(value: &self._config) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if !self.type.isEmpty { + try visitor.visitSingularStringField(value: self.type, fieldNumber: 1) + } + try { if let v = self._config { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } }() + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_XdsServer.ChannelCredentials, rhs: Grpc_ServiceConfig_XdsServer.ChannelCredentials) -> Bool { + if lhs.type != rhs.type {return false} + if lhs._config != rhs._config {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".XdsClusterResolverLoadBalancingPolicyConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "discovery_mechanisms"), + 2: .standard(proto: "xds_lb_policy"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeRepeatedMessageField(value: &self.discoveryMechanisms) }() + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.xdsLbPolicy) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.discoveryMechanisms.isEmpty { + try visitor.visitRepeatedMessageField(value: self.discoveryMechanisms, fieldNumber: 1) + } + if !self.xdsLbPolicy.isEmpty { + try visitor.visitRepeatedMessageField(value: self.xdsLbPolicy, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig, rhs: Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig) -> Bool { + if lhs.discoveryMechanisms != rhs.discoveryMechanisms {return false} + if lhs.xdsLbPolicy != rhs.xdsLbPolicy {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig.DiscoveryMechanism: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig.protoMessageName + ".DiscoveryMechanism" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "cluster"), + 2: .standard(proto: "lrs_load_reporting_server_name"), + 7: .standard(proto: "lrs_load_reporting_server"), + 3: .standard(proto: "max_concurrent_requests"), + 4: .same(proto: "type"), + 5: .standard(proto: "eds_service_name"), + 6: .standard(proto: "dns_hostname"), + 8: .standard(proto: "outlier_detection"), + 9: .standard(proto: "override_host_status"), + 10: .standard(proto: "telemetry_labels"), + ] + + fileprivate class _StorageClass { + var _cluster: String = String() + var _lrsLoadReportingServerName: SwiftProtobuf.Google_Protobuf_StringValue? = nil + var _lrsLoadReportingServer: Grpc_ServiceConfig_XdsServer? = nil + var _maxConcurrentRequests: SwiftProtobuf.Google_Protobuf_UInt32Value? = nil + var _type: Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig.DiscoveryMechanism.TypeEnum = .unknown + var _edsServiceName: String = String() + var _dnsHostname: String = String() + var _outlierDetection: Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig? = nil + var _overrideHostStatus: [Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig.HealthStatus] = [] + var _telemetryLabels: Dictionary = [:] + + static let defaultInstance = _StorageClass() + + private init() {} + + init(copying source: _StorageClass) { + _cluster = source._cluster + _lrsLoadReportingServerName = source._lrsLoadReportingServerName + _lrsLoadReportingServer = source._lrsLoadReportingServer + _maxConcurrentRequests = source._maxConcurrentRequests + _type = source._type + _edsServiceName = source._edsServiceName + _dnsHostname = source._dnsHostname + _outlierDetection = source._outlierDetection + _overrideHostStatus = source._overrideHostStatus + _telemetryLabels = source._telemetryLabels + } + } + + fileprivate mutating func _uniqueStorage() -> _StorageClass { + if !isKnownUniquelyReferenced(&_storage) { + _storage = _StorageClass(copying: _storage) + } + return _storage + } + + mutating func decodeMessage(decoder: inout D) throws { + _ = _uniqueStorage() + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &_storage._cluster) }() + case 2: try { try decoder.decodeSingularMessageField(value: &_storage._lrsLoadReportingServerName) }() + case 3: try { try decoder.decodeSingularMessageField(value: &_storage._maxConcurrentRequests) }() + case 4: try { try decoder.decodeSingularEnumField(value: &_storage._type) }() + case 5: try { try decoder.decodeSingularStringField(value: &_storage._edsServiceName) }() + case 6: try { try decoder.decodeSingularStringField(value: &_storage._dnsHostname) }() + case 7: try { try decoder.decodeSingularMessageField(value: &_storage._lrsLoadReportingServer) }() + case 8: try { try decoder.decodeSingularMessageField(value: &_storage._outlierDetection) }() + case 9: try { try decoder.decodeRepeatedEnumField(value: &_storage._overrideHostStatus) }() + case 10: try { try decoder.decodeMapField(fieldType: SwiftProtobuf._ProtobufMap.self, value: &_storage._telemetryLabels) }() + default: break + } + } + } + } + + func traverse(visitor: inout V) throws { + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if !_storage._cluster.isEmpty { + try visitor.visitSingularStringField(value: _storage._cluster, fieldNumber: 1) + } + try { if let v = _storage._lrsLoadReportingServerName { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } }() + try { if let v = _storage._maxConcurrentRequests { + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + } }() + if _storage._type != .unknown { + try visitor.visitSingularEnumField(value: _storage._type, fieldNumber: 4) + } + if !_storage._edsServiceName.isEmpty { + try visitor.visitSingularStringField(value: _storage._edsServiceName, fieldNumber: 5) + } + if !_storage._dnsHostname.isEmpty { + try visitor.visitSingularStringField(value: _storage._dnsHostname, fieldNumber: 6) + } + try { if let v = _storage._lrsLoadReportingServer { + try visitor.visitSingularMessageField(value: v, fieldNumber: 7) + } }() + try { if let v = _storage._outlierDetection { + try visitor.visitSingularMessageField(value: v, fieldNumber: 8) + } }() + if !_storage._overrideHostStatus.isEmpty { + try visitor.visitPackedEnumField(value: _storage._overrideHostStatus, fieldNumber: 9) + } + if !_storage._telemetryLabels.isEmpty { + try visitor.visitMapField(fieldType: SwiftProtobuf._ProtobufMap.self, value: _storage._telemetryLabels, fieldNumber: 10) + } + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig.DiscoveryMechanism, rhs: Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig.DiscoveryMechanism) -> Bool { + if lhs._storage !== rhs._storage { + let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in + let _storage = _args.0 + let rhs_storage = _args.1 + if _storage._cluster != rhs_storage._cluster {return false} + if _storage._lrsLoadReportingServerName != rhs_storage._lrsLoadReportingServerName {return false} + if _storage._lrsLoadReportingServer != rhs_storage._lrsLoadReportingServer {return false} + if _storage._maxConcurrentRequests != rhs_storage._maxConcurrentRequests {return false} + if _storage._type != rhs_storage._type {return false} + if _storage._edsServiceName != rhs_storage._edsServiceName {return false} + if _storage._dnsHostname != rhs_storage._dnsHostname {return false} + if _storage._outlierDetection != rhs_storage._outlierDetection {return false} + if _storage._overrideHostStatus != rhs_storage._overrideHostStatus {return false} + if _storage._telemetryLabels != rhs_storage._telemetryLabels {return false} + return true + } + if !storagesAreEqual {return false} + } + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig.DiscoveryMechanism.TypeEnum: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "UNKNOWN"), + 1: .same(proto: "EDS"), + 2: .same(proto: "LOGICAL_DNS"), + ] +} + +extension Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".XdsClusterImplLoadBalancingPolicyConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "cluster"), + 2: .standard(proto: "eds_service_name"), + 3: .standard(proto: "lrs_load_reporting_server_name"), + 7: .standard(proto: "lrs_load_reporting_server"), + 4: .standard(proto: "max_concurrent_requests"), + 5: .standard(proto: "drop_categories"), + 6: .standard(proto: "child_policy"), + 8: .standard(proto: "telemetry_labels"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.cluster) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.edsServiceName) }() + case 3: try { try decoder.decodeSingularMessageField(value: &self._lrsLoadReportingServerName) }() + case 4: try { try decoder.decodeSingularMessageField(value: &self._maxConcurrentRequests) }() + case 5: try { try decoder.decodeRepeatedMessageField(value: &self.dropCategories) }() + case 6: try { try decoder.decodeRepeatedMessageField(value: &self.childPolicy) }() + case 7: try { try decoder.decodeSingularMessageField(value: &self._lrsLoadReportingServer) }() + case 8: try { try decoder.decodeMapField(fieldType: SwiftProtobuf._ProtobufMap.self, value: &self.telemetryLabels) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if !self.cluster.isEmpty { + try visitor.visitSingularStringField(value: self.cluster, fieldNumber: 1) + } + if !self.edsServiceName.isEmpty { + try visitor.visitSingularStringField(value: self.edsServiceName, fieldNumber: 2) + } + try { if let v = self._lrsLoadReportingServerName { + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + } }() + try { if let v = self._maxConcurrentRequests { + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) + } }() + if !self.dropCategories.isEmpty { + try visitor.visitRepeatedMessageField(value: self.dropCategories, fieldNumber: 5) + } + if !self.childPolicy.isEmpty { + try visitor.visitRepeatedMessageField(value: self.childPolicy, fieldNumber: 6) + } + try { if let v = self._lrsLoadReportingServer { + try visitor.visitSingularMessageField(value: v, fieldNumber: 7) + } }() + if !self.telemetryLabels.isEmpty { + try visitor.visitMapField(fieldType: SwiftProtobuf._ProtobufMap.self, value: self.telemetryLabels, fieldNumber: 8) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig, rhs: Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig) -> Bool { + if lhs.cluster != rhs.cluster {return false} + if lhs.edsServiceName != rhs.edsServiceName {return false} + if lhs._lrsLoadReportingServerName != rhs._lrsLoadReportingServerName {return false} + if lhs._lrsLoadReportingServer != rhs._lrsLoadReportingServer {return false} + if lhs._maxConcurrentRequests != rhs._maxConcurrentRequests {return false} + if lhs.dropCategories != rhs.dropCategories {return false} + if lhs.childPolicy != rhs.childPolicy {return false} + if lhs.telemetryLabels != rhs.telemetryLabels {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig.DropCategory: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig.protoMessageName + ".DropCategory" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "category"), + 2: .standard(proto: "requests_per_million"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.category) }() + case 2: try { try decoder.decodeSingularUInt32Field(value: &self.requestsPerMillion) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.category.isEmpty { + try visitor.visitSingularStringField(value: self.category, fieldNumber: 1) + } + if self.requestsPerMillion != 0 { + try visitor.visitSingularUInt32Field(value: self.requestsPerMillion, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig.DropCategory, rhs: Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig.DropCategory) -> Bool { + if lhs.category != rhs.category {return false} + if lhs.requestsPerMillion != rhs.requestsPerMillion {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_EdsLoadBalancingPolicyConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".EdsLoadBalancingPolicyConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "cluster"), + 2: .standard(proto: "eds_service_name"), + 3: .standard(proto: "lrs_load_reporting_server_name"), + 4: .standard(proto: "locality_picking_policy"), + 5: .standard(proto: "endpoint_picking_policy"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.cluster) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.edsServiceName) }() + case 3: try { try decoder.decodeSingularMessageField(value: &self._lrsLoadReportingServerName) }() + case 4: try { try decoder.decodeRepeatedMessageField(value: &self.localityPickingPolicy) }() + case 5: try { try decoder.decodeRepeatedMessageField(value: &self.endpointPickingPolicy) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if !self.cluster.isEmpty { + try visitor.visitSingularStringField(value: self.cluster, fieldNumber: 1) + } + if !self.edsServiceName.isEmpty { + try visitor.visitSingularStringField(value: self.edsServiceName, fieldNumber: 2) + } + try { if let v = self._lrsLoadReportingServerName { + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + } }() + if !self.localityPickingPolicy.isEmpty { + try visitor.visitRepeatedMessageField(value: self.localityPickingPolicy, fieldNumber: 4) + } + if !self.endpointPickingPolicy.isEmpty { + try visitor.visitRepeatedMessageField(value: self.endpointPickingPolicy, fieldNumber: 5) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_EdsLoadBalancingPolicyConfig, rhs: Grpc_ServiceConfig_EdsLoadBalancingPolicyConfig) -> Bool { + if lhs.cluster != rhs.cluster {return false} + if lhs.edsServiceName != rhs.edsServiceName {return false} + if lhs._lrsLoadReportingServerName != rhs._lrsLoadReportingServerName {return false} + if lhs.localityPickingPolicy != rhs.localityPickingPolicy {return false} + if lhs.endpointPickingPolicy != rhs.endpointPickingPolicy {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_RingHashLoadBalancingConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".RingHashLoadBalancingConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "min_ring_size"), + 2: .standard(proto: "max_ring_size"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularUInt64Field(value: &self.minRingSize) }() + case 2: try { try decoder.decodeSingularUInt64Field(value: &self.maxRingSize) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.minRingSize != 0 { + try visitor.visitSingularUInt64Field(value: self.minRingSize, fieldNumber: 1) + } + if self.maxRingSize != 0 { + try visitor.visitSingularUInt64Field(value: self.maxRingSize, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_RingHashLoadBalancingConfig, rhs: Grpc_ServiceConfig_RingHashLoadBalancingConfig) -> Bool { + if lhs.minRingSize != rhs.minRingSize {return false} + if lhs.maxRingSize != rhs.maxRingSize {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".LrsLoadBalancingPolicyConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "cluster_name"), + 2: .standard(proto: "eds_service_name"), + 3: .standard(proto: "lrs_load_reporting_server_name"), + 4: .same(proto: "locality"), + 5: .standard(proto: "child_policy"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.clusterName) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.edsServiceName) }() + case 3: try { try decoder.decodeSingularStringField(value: &self.lrsLoadReportingServerName) }() + case 4: try { try decoder.decodeSingularMessageField(value: &self._locality) }() + case 5: try { try decoder.decodeRepeatedMessageField(value: &self.childPolicy) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if !self.clusterName.isEmpty { + try visitor.visitSingularStringField(value: self.clusterName, fieldNumber: 1) + } + if !self.edsServiceName.isEmpty { + try visitor.visitSingularStringField(value: self.edsServiceName, fieldNumber: 2) + } + if !self.lrsLoadReportingServerName.isEmpty { + try visitor.visitSingularStringField(value: self.lrsLoadReportingServerName, fieldNumber: 3) + } + try { if let v = self._locality { + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) + } }() + if !self.childPolicy.isEmpty { + try visitor.visitRepeatedMessageField(value: self.childPolicy, fieldNumber: 5) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig, rhs: Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig) -> Bool { + if lhs.clusterName != rhs.clusterName {return false} + if lhs.edsServiceName != rhs.edsServiceName {return false} + if lhs.lrsLoadReportingServerName != rhs.lrsLoadReportingServerName {return false} + if lhs._locality != rhs._locality {return false} + if lhs.childPolicy != rhs.childPolicy {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig.Locality: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig.protoMessageName + ".Locality" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "region"), + 2: .same(proto: "zone"), + 3: .same(proto: "subzone"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.region) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.zone) }() + case 3: try { try decoder.decodeSingularStringField(value: &self.subzone) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.region.isEmpty { + try visitor.visitSingularStringField(value: self.region, fieldNumber: 1) + } + if !self.zone.isEmpty { + try visitor.visitSingularStringField(value: self.zone, fieldNumber: 2) + } + if !self.subzone.isEmpty { + try visitor.visitSingularStringField(value: self.subzone, fieldNumber: 3) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig.Locality, rhs: Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig.Locality) -> Bool { + if lhs.region != rhs.region {return false} + if lhs.zone != rhs.zone {return false} + if lhs.subzone != rhs.subzone {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_XdsWrrLocalityLoadBalancingPolicyConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".XdsWrrLocalityLoadBalancingPolicyConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "child_policy"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeRepeatedMessageField(value: &self.childPolicy) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.childPolicy.isEmpty { + try visitor.visitRepeatedMessageField(value: self.childPolicy, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_XdsWrrLocalityLoadBalancingPolicyConfig, rhs: Grpc_ServiceConfig_XdsWrrLocalityLoadBalancingPolicyConfig) -> Bool { + if lhs.childPolicy != rhs.childPolicy {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_LeastRequestLocalityLoadBalancingPolicyConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".LeastRequestLocalityLoadBalancingPolicyConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "choice_count"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularUInt64Field(value: &self.choiceCount) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.choiceCount != 0 { + try visitor.visitSingularUInt64Field(value: self.choiceCount, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_LeastRequestLocalityLoadBalancingPolicyConfig, rhs: Grpc_ServiceConfig_LeastRequestLocalityLoadBalancingPolicyConfig) -> Bool { + if lhs.choiceCount != rhs.choiceCount {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".OverrideHostLoadBalancingPolicyConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "override_host_status"), + 2: .standard(proto: "child_policy"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeRepeatedEnumField(value: &self.overrideHostStatus) }() + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.childPolicy) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.overrideHostStatus.isEmpty { + try visitor.visitPackedEnumField(value: self.overrideHostStatus, fieldNumber: 1) + } + if !self.childPolicy.isEmpty { + try visitor.visitRepeatedMessageField(value: self.childPolicy, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig, rhs: Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig) -> Bool { + if lhs.overrideHostStatus != rhs.overrideHostStatus {return false} + if lhs.childPolicy != rhs.childPolicy {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig.HealthStatus: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "UNKNOWN"), + 1: .same(proto: "HEALTHY"), + 3: .same(proto: "DRAINING"), + ] +} + +extension Grpc_ServiceConfig_XdsConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".XdsConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "balancer_name"), + 2: .standard(proto: "child_policy"), + 3: .standard(proto: "fallback_policy"), + 4: .standard(proto: "eds_service_name"), + 5: .standard(proto: "lrs_load_reporting_server_name"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.balancerName) }() + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.childPolicy) }() + case 3: try { try decoder.decodeRepeatedMessageField(value: &self.fallbackPolicy) }() + case 4: try { try decoder.decodeSingularStringField(value: &self.edsServiceName) }() + case 5: try { try decoder.decodeSingularMessageField(value: &self._lrsLoadReportingServerName) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if !self.balancerName.isEmpty { + try visitor.visitSingularStringField(value: self.balancerName, fieldNumber: 1) + } + if !self.childPolicy.isEmpty { + try visitor.visitRepeatedMessageField(value: self.childPolicy, fieldNumber: 2) + } + if !self.fallbackPolicy.isEmpty { + try visitor.visitRepeatedMessageField(value: self.fallbackPolicy, fieldNumber: 3) + } + if !self.edsServiceName.isEmpty { + try visitor.visitSingularStringField(value: self.edsServiceName, fieldNumber: 4) + } + try { if let v = self._lrsLoadReportingServerName { + try visitor.visitSingularMessageField(value: v, fieldNumber: 5) + } }() + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_XdsConfig, rhs: Grpc_ServiceConfig_XdsConfig) -> Bool { + if lhs.balancerName != rhs.balancerName {return false} + if lhs.childPolicy != rhs.childPolicy {return false} + if lhs.fallbackPolicy != rhs.fallbackPolicy {return false} + if lhs.edsServiceName != rhs.edsServiceName {return false} + if lhs._lrsLoadReportingServerName != rhs._lrsLoadReportingServerName {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_LoadBalancingConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".LoadBalancingConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 4: .same(proto: "pick_first"), + 1: .same(proto: "round_robin"), + 20: .same(proto: "weighted_round_robin"), + 3: .same(proto: "grpclb"), + 9: .same(proto: "priority_experimental"), + 10: .same(proto: "weighted_target_experimental"), + 15: .unique(proto: "outlier_detection", json: "outlier_detection_experimental"), + 19: .unique(proto: "rls", json: "rls_experimental"), + 14: .same(proto: "xds_cluster_manager_experimental"), + 6: .same(proto: "cds_experimental"), + 11: .same(proto: "xds_cluster_resolver_experimental"), + 12: .same(proto: "xds_cluster_impl_experimental"), + 18: .same(proto: "override_host_experimental"), + 16: .same(proto: "xds_wrr_locality_experimental"), + 13: .same(proto: "ring_hash_experimental"), + 17: .same(proto: "least_request_experimental"), + 8: .same(proto: "lrs_experimental"), + 7: .same(proto: "eds_experimental"), + 2: .same(proto: "xds"), + 5: .same(proto: "xds_experimental"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { + var v: Grpc_ServiceConfig_RoundRobinConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .roundRobin(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .roundRobin(v) + } + }() + case 2: try { + var v: Grpc_ServiceConfig_XdsConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .xds(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .xds(v) + } + }() + case 3: try { + var v: Grpc_ServiceConfig_GrpcLbConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .grpclb(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .grpclb(v) + } + }() + case 4: try { + var v: Grpc_ServiceConfig_PickFirstConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .pickFirst(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .pickFirst(v) + } + }() + case 5: try { + var v: Grpc_ServiceConfig_XdsConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .xdsExperimental(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .xdsExperimental(v) + } + }() + case 6: try { + var v: Grpc_ServiceConfig_CdsConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .cdsExperimental(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .cdsExperimental(v) + } + }() + case 7: try { + var v: Grpc_ServiceConfig_EdsLoadBalancingPolicyConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .edsExperimental(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .edsExperimental(v) + } + }() + case 8: try { + var v: Grpc_ServiceConfig_LrsLoadBalancingPolicyConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .lrsExperimental(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .lrsExperimental(v) + } + }() + case 9: try { + var v: Grpc_ServiceConfig_PriorityLoadBalancingPolicyConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .priorityExperimental(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .priorityExperimental(v) + } + }() + case 10: try { + var v: Grpc_ServiceConfig_WeightedTargetLoadBalancingPolicyConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .weightedTargetExperimental(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .weightedTargetExperimental(v) + } + }() + case 11: try { + var v: Grpc_ServiceConfig_XdsClusterResolverLoadBalancingPolicyConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .xdsClusterResolverExperimental(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .xdsClusterResolverExperimental(v) + } + }() + case 12: try { + var v: Grpc_ServiceConfig_XdsClusterImplLoadBalancingPolicyConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .xdsClusterImplExperimental(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .xdsClusterImplExperimental(v) + } + }() + case 13: try { + var v: Grpc_ServiceConfig_RingHashLoadBalancingConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .ringHashExperimental(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .ringHashExperimental(v) + } + }() + case 14: try { + var v: Grpc_ServiceConfig_XdsClusterManagerLoadBalancingPolicyConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .xdsClusterManagerExperimental(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .xdsClusterManagerExperimental(v) + } + }() + case 15: try { + var v: Grpc_ServiceConfig_OutlierDetectionLoadBalancingConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .outlierDetection(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .outlierDetection(v) + } + }() + case 16: try { + var v: Grpc_ServiceConfig_XdsWrrLocalityLoadBalancingPolicyConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .xdsWrrLocalityExperimental(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .xdsWrrLocalityExperimental(v) + } + }() + case 17: try { + var v: Grpc_ServiceConfig_LeastRequestLocalityLoadBalancingPolicyConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .leastRequestExperimental(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .leastRequestExperimental(v) + } + }() + case 18: try { + var v: Grpc_ServiceConfig_OverrideHostLoadBalancingPolicyConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .overrideHostExperimental(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .overrideHostExperimental(v) + } + }() + case 19: try { + var v: Grpc_ServiceConfig_RlsLoadBalancingPolicyConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .rls(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .rls(v) + } + }() + case 20: try { + var v: Grpc_ServiceConfig_WeightedRoundRobinLbConfig? + var hadOneofValue = false + if let current = self.policy { + hadOneofValue = true + if case .weightedRoundRobin(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.policy = .weightedRoundRobin(v) + } + }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + switch self.policy { + case .roundRobin?: try { + guard case .roundRobin(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + }() + case .xds?: try { + guard case .xds(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + }() + case .grpclb?: try { + guard case .grpclb(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + }() + case .pickFirst?: try { + guard case .pickFirst(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) + }() + case .xdsExperimental?: try { + guard case .xdsExperimental(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 5) + }() + case .cdsExperimental?: try { + guard case .cdsExperimental(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 6) + }() + case .edsExperimental?: try { + guard case .edsExperimental(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 7) + }() + case .lrsExperimental?: try { + guard case .lrsExperimental(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 8) + }() + case .priorityExperimental?: try { + guard case .priorityExperimental(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 9) + }() + case .weightedTargetExperimental?: try { + guard case .weightedTargetExperimental(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 10) + }() + case .xdsClusterResolverExperimental?: try { + guard case .xdsClusterResolverExperimental(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 11) + }() + case .xdsClusterImplExperimental?: try { + guard case .xdsClusterImplExperimental(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 12) + }() + case .ringHashExperimental?: try { + guard case .ringHashExperimental(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 13) + }() + case .xdsClusterManagerExperimental?: try { + guard case .xdsClusterManagerExperimental(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 14) + }() + case .outlierDetection?: try { + guard case .outlierDetection(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 15) + }() + case .xdsWrrLocalityExperimental?: try { + guard case .xdsWrrLocalityExperimental(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 16) + }() + case .leastRequestExperimental?: try { + guard case .leastRequestExperimental(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 17) + }() + case .overrideHostExperimental?: try { + guard case .overrideHostExperimental(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 18) + }() + case .rls?: try { + guard case .rls(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 19) + }() + case .weightedRoundRobin?: try { + guard case .weightedRoundRobin(let v)? = self.policy else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 20) + }() + case nil: break + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_LoadBalancingConfig, rhs: Grpc_ServiceConfig_LoadBalancingConfig) -> Bool { + if lhs.policy != rhs.policy {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_ServiceConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".ServiceConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "load_balancing_policy"), + 4: .standard(proto: "load_balancing_config"), + 2: .standard(proto: "method_config"), + 3: .standard(proto: "retry_throttling"), + 5: .standard(proto: "health_check_config"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularEnumField(value: &self.loadBalancingPolicy) }() + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.methodConfig) }() + case 3: try { try decoder.decodeSingularMessageField(value: &self._retryThrottling) }() + case 4: try { try decoder.decodeRepeatedMessageField(value: &self.loadBalancingConfig) }() + case 5: try { try decoder.decodeSingularMessageField(value: &self._healthCheckConfig) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if self.loadBalancingPolicy != .unspecified { + try visitor.visitSingularEnumField(value: self.loadBalancingPolicy, fieldNumber: 1) + } + if !self.methodConfig.isEmpty { + try visitor.visitRepeatedMessageField(value: self.methodConfig, fieldNumber: 2) + } + try { if let v = self._retryThrottling { + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + } }() + if !self.loadBalancingConfig.isEmpty { + try visitor.visitRepeatedMessageField(value: self.loadBalancingConfig, fieldNumber: 4) + } + try { if let v = self._healthCheckConfig { + try visitor.visitSingularMessageField(value: v, fieldNumber: 5) + } }() + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_ServiceConfig, rhs: Grpc_ServiceConfig_ServiceConfig) -> Bool { + if lhs.loadBalancingPolicy != rhs.loadBalancingPolicy {return false} + if lhs.loadBalancingConfig != rhs.loadBalancingConfig {return false} + if lhs.methodConfig != rhs.methodConfig {return false} + if lhs._retryThrottling != rhs._retryThrottling {return false} + if lhs._healthCheckConfig != rhs._healthCheckConfig {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_ServiceConfig.LoadBalancingPolicy: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "UNSPECIFIED"), + 1: .same(proto: "ROUND_ROBIN"), + ] +} + +extension Grpc_ServiceConfig_ServiceConfig.RetryThrottlingPolicy: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_ServiceConfig_ServiceConfig.protoMessageName + ".RetryThrottlingPolicy" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "max_tokens"), + 2: .standard(proto: "token_ratio"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularUInt32Field(value: &self.maxTokens) }() + case 2: try { try decoder.decodeSingularFloatField(value: &self.tokenRatio) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.maxTokens != 0 { + try visitor.visitSingularUInt32Field(value: self.maxTokens, fieldNumber: 1) + } + if self.tokenRatio != 0 { + try visitor.visitSingularFloatField(value: self.tokenRatio, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_ServiceConfig.RetryThrottlingPolicy, rhs: Grpc_ServiceConfig_ServiceConfig.RetryThrottlingPolicy) -> Bool { + if lhs.maxTokens != rhs.maxTokens {return false} + if lhs.tokenRatio != rhs.tokenRatio {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Grpc_ServiceConfig_ServiceConfig.HealthCheckConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = Grpc_ServiceConfig_ServiceConfig.protoMessageName + ".HealthCheckConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "service_name"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularMessageField(value: &self._serviceName) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + try { if let v = self._serviceName { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } }() + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Grpc_ServiceConfig_ServiceConfig.HealthCheckConfig, rhs: Grpc_ServiceConfig_ServiceConfig.HealthCheckConfig) -> Bool { + if lhs._serviceName != rhs._serviceName {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} From c58dea7e256757ba51667bb1d7ed7f8debbfe32c Mon Sep 17 00:00:00 2001 From: George Barnett Date: Mon, 5 Feb 2024 11:18:15 +0000 Subject: [PATCH 3/6] format --- Sources/GRPCCore/Configuration/MethodConfiguration.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/GRPCCore/Configuration/MethodConfiguration.swift b/Sources/GRPCCore/Configuration/MethodConfiguration.swift index fdf9d1f5f..9ba0c1839 100644 --- a/Sources/GRPCCore/Configuration/MethodConfiguration.swift +++ b/Sources/GRPCCore/Configuration/MethodConfiguration.swift @@ -35,7 +35,7 @@ public struct MethodConfiguration: Hashable, Sendable { /// If the method is empty then the configuration will be the default for all methods in the /// specified service. public var method: String - + /// Create a new name. /// /// If the service is empty then `method` must also be empty and the configuration specifies @@ -109,7 +109,7 @@ public struct MethodConfiguration: Hashable, Sendable { public var executionPolicy: ExecutionPolicy? /// Create an execution configuration. - /// + /// /// - Parameters: /// - names: The names of methods this configuration applies to. /// - timeout: The default timeout for the RPC. From 96e7530dfb2c7160cd8aa6143708199df541ee45 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Tue, 6 Feb 2024 09:21:18 +0000 Subject: [PATCH 4/6] fix typos and max attempts validation --- .../Configuration/MethodConfiguration.swift | 8 ++-- .../Configuration/ServiceConfiguration.swift | 2 +- .../MethodConfigurationCodingTests.swift | 39 ++++++++++--------- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/Sources/GRPCCore/Configuration/MethodConfiguration.swift b/Sources/GRPCCore/Configuration/MethodConfiguration.swift index 9ba0c1839..0e0af5d1b 100644 --- a/Sources/GRPCCore/Configuration/MethodConfiguration.swift +++ b/Sources/GRPCCore/Configuration/MethodConfiguration.swift @@ -81,7 +81,7 @@ public struct MethodConfiguration: Hashable, Sendable { /// The maximum allowed payload size in bytes for an individual message. /// /// If a client attempts to send an object larger than this value, it will not be sent and the - /// client will see a error. Note that 0 is a valid value, meaning that the request message + /// client will see an error. Note that 0 is a valid value, meaning that the request message /// must be empty. public var maxRequestMessageBytes: Int? @@ -311,7 +311,7 @@ public struct HedgingPolicy: Hashable, Sendable { /// - Parameters: /// - maximumAttempts: The maximum number of attempts allowed for the RPC. /// - hedgingDelay: The delay between each hedged RPC. - /// - nonFatalStatusCodes: The set of status codes which indicated other hedged RPCs may still + /// - nonFatalStatusCodes: The set of status codes which indicate other hedged RPCs may still /// succeed. /// - Precondition: `maximumAttempts` must be greater than zero. public init( @@ -337,10 +337,10 @@ public struct HedgingPolicy: Hashable, Sendable { } private func validateMaxAttempts(_ value: Int) throws -> Int { - guard value > 0 else { + guard value > 1 else { throw RuntimeError( code: .invalidArgument, - message: "max_attempts must be greater than zero (was \(value))" + message: "max_attempts must be greater than one (was \(value))" ) } diff --git a/Sources/GRPCCore/Configuration/ServiceConfiguration.swift b/Sources/GRPCCore/Configuration/ServiceConfiguration.swift index 17d178623..54adeaf48 100644 --- a/Sources/GRPCCore/Configuration/ServiceConfiguration.swift +++ b/Sources/GRPCCore/Configuration/ServiceConfiguration.swift @@ -244,7 +244,7 @@ extension ServiceConfiguration { /// /// - Parameters: /// - maxTokens: The initial, and maximum number of tokens. Must be greater than zero. - /// - tokenRatio: The amount of tokens to add on each successful RPc. Must be greater + /// - tokenRatio: The amount of tokens to add on each successful RPC. Must be greater /// than zero. public init(maxTokens: Int, tokenRatio: Double) throws { self.maxTokens = maxTokens diff --git a/Tests/GRPCCoreTests/Configuration/MethodConfigurationCodingTests.swift b/Tests/GRPCCoreTests/Configuration/MethodConfigurationCodingTests.swift index aeeb7e343..0e7b4ab92 100644 --- a/Tests/GRPCCoreTests/Configuration/MethodConfigurationCodingTests.swift +++ b/Tests/GRPCCoreTests/Configuration/MethodConfigurationCodingTests.swift @@ -198,20 +198,20 @@ internal final class MethodConfigurationCodingTests: XCTestCase { func testDecodeRetryPolicy() throws { let json = """ { - "maxAttempts": 1, + "maxAttempts": 3, "initialBackoff": "1s", "maxBackoff": "3s", "backoffMultiplier": 1.6, - "retryableStatusCodes": ["ABORTED"] + "retryableStatusCodes": ["ABORTED", "UNAVAILABLE"] } """ let expected = RetryPolicy( - maximumAttempts: 1, + maximumAttempts: 3, initialBackoff: .seconds(1), maximumBackoff: .seconds(3), backoffMultiplier: 1.6, - retryableStatusCodes: [.aborted] + retryableStatusCodes: [.aborted, .unavailable] ) let decoded = try self.decoder.decode(RetryPolicy.self, from: Data(json.utf8)) @@ -233,17 +233,20 @@ internal final class MethodConfigurationCodingTests: XCTestCase { } func testDecodeRetryPolicyWithInvalidRetryMaxAttempts() throws { - let json = """ - { - "maxAttempts": -1, - "initialBackoff": "1s", - "maxBackoff": "3s", - "backoffMultiplier": 1.6, - "retryableStatusCodes": ["ABORTED"] - } - """ + let cases = ["-1", "0", "1"] + for maxAttempts in cases { + let json = """ + { + "maxAttempts": \(maxAttempts), + "initialBackoff": "1s", + "maxBackoff": "3s", + "backoffMultiplier": 1.6, + "retryableStatusCodes": ["ABORTED"] + } + """ - try self.testDecodeThrowsRuntimeError(json: json, as: RetryPolicy.self) + try self.testDecodeThrowsRuntimeError(json: json, as: RetryPolicy.self) + } } func testDecodeRetryPolicyWithInvalidInitialBackoff() throws { @@ -251,7 +254,7 @@ internal final class MethodConfigurationCodingTests: XCTestCase { for backoff in cases { let json = """ { - "maxAttempts": -1, + "maxAttempts": 3, "initialBackoff": "\(backoff)", "maxBackoff": "3s", "backoffMultiplier": 1.6, @@ -267,7 +270,7 @@ internal final class MethodConfigurationCodingTests: XCTestCase { for backoff in cases { let json = """ { - "maxAttempts": -1, + "maxAttempts": 3, "initialBackoff": "1s", "maxBackoff": "\(backoff)", "backoffMultiplier": 1.6, @@ -283,7 +286,7 @@ internal final class MethodConfigurationCodingTests: XCTestCase { for multiplier in cases { let json = """ { - "maxAttempts": -1, + "maxAttempts": 3, "initialBackoff": "1s", "maxBackoff": "3s", "backoffMultiplier": \(multiplier), @@ -297,7 +300,7 @@ internal final class MethodConfigurationCodingTests: XCTestCase { func testDecodeRetryPolicyWithEmptyRetryableStatusCodes() throws { let json = """ { - "maxAttempts": -1, + "maxAttempts": 3, "initialBackoff": "1s", "maxBackoff": "3s", "backoffMultiplier": 1, From d807959bedcb059c4f00602072c64b7428c88295 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Tue, 6 Feb 2024 14:03:37 +0000 Subject: [PATCH 5/6] fix test --- .../Configuration/MethodConfigurationCodingTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/GRPCCoreTests/Configuration/MethodConfigurationCodingTests.swift b/Tests/GRPCCoreTests/Configuration/MethodConfigurationCodingTests.swift index 0e7b4ab92..a9365909c 100644 --- a/Tests/GRPCCoreTests/Configuration/MethodConfigurationCodingTests.swift +++ b/Tests/GRPCCoreTests/Configuration/MethodConfigurationCodingTests.swift @@ -220,7 +220,7 @@ internal final class MethodConfigurationCodingTests: XCTestCase { func testEncodeDecodeRetryPolicy() throws { let policy = RetryPolicy( - maximumAttempts: 1, + maximumAttempts: 3, initialBackoff: .seconds(1), maximumBackoff: .seconds(3), backoffMultiplier: 1.6, From e48b4d1648bcebe36a00cf2c744d950bf6607ce3 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Tue, 6 Feb 2024 14:31:39 +0000 Subject: [PATCH 6/6] fix the other test --- Tests/GRPCCoreTests/Call/Client/RetryDelaySequenceTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/GRPCCoreTests/Call/Client/RetryDelaySequenceTests.swift b/Tests/GRPCCoreTests/Call/Client/RetryDelaySequenceTests.swift index 09bc182cd..4ecc2fc65 100644 --- a/Tests/GRPCCoreTests/Call/Client/RetryDelaySequenceTests.swift +++ b/Tests/GRPCCoreTests/Call/Client/RetryDelaySequenceTests.swift @@ -21,7 +21,7 @@ import XCTest final class RetryDelaySequenceTests: XCTestCase { func testSequence() { let policy = RetryPolicy( - maximumAttempts: 1, // ignored here + maximumAttempts: 3, // ignored here initialBackoff: .seconds(1), maximumBackoff: .seconds(8), backoffMultiplier: 2.0, @@ -41,7 +41,7 @@ final class RetryDelaySequenceTests: XCTestCase { func testSequenceSupportsMultipleIteration() { let policy = RetryPolicy( - maximumAttempts: 1, // ignored here + maximumAttempts: 3, // ignored here initialBackoff: .seconds(1), maximumBackoff: .seconds(8), backoffMultiplier: 2.0,