From 6217bad067b4a9849fc0ccda3fb97bd52ad28c42 Mon Sep 17 00:00:00 2001 From: iczero Date: Fri, 4 Jul 2025 19:21:01 -0700 Subject: [PATCH] update tonic, prost, and protobufs --- .protoc-version | 2 +- Cargo.lock | 48 +- Cargo.toml | 9 +- protobufs.toml | 10 +- src/generated/envoy.admin.v3.rs | 10 + src/generated/envoy.admin.v3.serde.rs | 6 + src/generated/envoy.config.accesslog.v3.rs | 45 +- src/generated/envoy.config.bootstrap.v3.rs | 4 +- src/generated/envoy.config.cluster.v3.rs | 115 +- .../envoy.config.cluster.v3.serde.rs | 54 + .../envoy.config.common.matcher.v3.rs | 21 +- .../envoy.config.common.matcher.v3.serde.rs | 18 + src/generated/envoy.config.core.v3.rs | 362 +- src/generated/envoy.config.core.v3.serde.rs | 950 ++++- src/generated/envoy.config.endpoint.v3.rs | 117 +- .../envoy.config.endpoint.v3.serde.rs | 344 ++ .../envoy.config.grpc_credential.v3.rs | 27 - .../envoy.config.grpc_credential.v3.serde.rs | 109 - src/generated/envoy.config.listener.v3.rs | 100 +- .../envoy.config.listener.v3.serde.rs | 273 +- src/generated/envoy.config.overload.v3.rs | 9 + .../envoy.config.overload.v3.serde.rs | 3 + src/generated/envoy.config.rbac.v3.rs | 164 +- src/generated/envoy.config.rbac.v3.serde.rs | 224 ++ src/generated/envoy.config.route.v3.rs | 223 +- src/generated/envoy.config.route.v3.serde.rs | 304 ++ src/generated/envoy.config.tap.v3.rs | 9 + src/generated/envoy.config.tap.v3.serde.rs | 18 + src/generated/envoy.config.trace.v3.rs | 193 +- src/generated/envoy.config.trace.v3.serde.rs | 524 +-- src/generated/envoy.data.accesslog.v3.rs | 49 +- src/generated/envoy.data.tap.v3.rs | 25 +- src/generated/envoy.data.tap.v3.serde.rs | 121 + .../envoy.extensions.clusters.aggregate.v3.rs | 29 + ....extensions.clusters.aggregate.v3.serde.rs | 110 + .../envoy.extensions.common.ratelimit.v3.rs | 39 +- ...oy.extensions.common.ratelimit.v3.serde.rs | 89 + ...voy.extensions.filters.http.ext_proc.v3.rs | 24 +- ...tensions.filters.http.ext_proc.v3.serde.rs | 3 + ...envoy.extensions.filters.http.router.v3.rs | 4 +- ...ters.network.http_connection_manager.v3.rs | 202 +- ...etwork.http_connection_manager.v3.serde.rs | 18 + ...voy.extensions.transport_sockets.tls.v3.rs | 108 +- ...tensions.transport_sockets.tls.v3.serde.rs | 129 + src/generated/envoy.r#type.http.v3.rs | 23 + src/generated/envoy.r#type.http.v3.serde.rs | 125 + src/generated/envoy.r#type.matcher.v3.rs | 63 +- .../envoy.r#type.matcher.v3.serde.rs | 105 + src/generated/envoy.r#type.metadata.v3.rs | 32 +- src/generated/envoy.r#type.v3.rs | 56 + src/generated/envoy.service.accesslog.v3.rs | 14 +- src/generated/envoy.service.auth.v3.rs | 16 +- src/generated/envoy.service.cluster.v3.rs | 14 +- src/generated/envoy.service.discovery.v3.rs | 218 +- .../envoy.service.discovery.v3.serde.rs | 146 + src/generated/envoy.service.endpoint.v3.rs | 28 +- .../envoy.service.event_reporting.v3.rs | 14 +- src/generated/envoy.service.ext_proc.v3.rs | 251 +- .../envoy.service.ext_proc.v3.serde.rs | 277 ++ src/generated/envoy.service.extension.v3.rs | 62 +- src/generated/envoy.service.health.v3.rs | 14 +- src/generated/envoy.service.listener.v3.rs | 14 +- src/generated/envoy.service.load_stats.v3.rs | 14 +- src/generated/envoy.service.metrics.v3.rs | 14 +- .../envoy.service.network_ext_proc.v3.rs | 533 +++ ...envoy.service.network_ext_proc.v3.serde.rs | 556 +++ .../envoy.service.rate_limit_quota.v3.rs | 14 +- src/generated/envoy.service.ratelimit.v3.rs | 20 +- .../envoy.service.ratelimit.v3.serde.rs | 3 + ...e.v3.rs => envoy.service.redis_auth.v3.rs} | 186 +- .../envoy.service.redis_auth.v3.serde.rs | 233 ++ src/generated/envoy.service.route.v3.rs | 42 +- src/generated/envoy.service.runtime.v3.rs | 14 +- src/generated/envoy.service.secret.v3.rs | 14 +- src/generated/envoy.service.status.v3.rs | 20 +- .../envoy.service.status.v3.serde.rs | 3 + src/generated/envoy.service.tap.v3.rs | 14 +- src/generated/envoy.service.trace.v3.serde.rs | 270 -- src/generated/google.api.expr.v1alpha1.rs | 179 +- .../google.api.expr.v1alpha1.serde.rs | 358 ++ src/generated/google.api.rs | 60 +- src/generated/google.protobuf.rs | 226 +- src/generated/google.protobuf.serde.rs | 395 ++ src/generated/mod.rs | 39 +- src/generated/opencensus.proto.resource.v1.rs | 24 - .../opencensus.proto.resource.v1.serde.rs | 110 - src/generated/opencensus.proto.trace.v1.rs | 871 ----- .../opencensus.proto.trace.v1.serde.rs | 3180 ----------------- src/generated/xds.core.v3.rs | 23 + src/generated/xds.core.v3.serde.rs | 110 + src/generated/xds.r#type.matcher.v3.rs | 8 + src/generated/xds.r#type.matcher.v3.serde.rs | 18 + src/lib.rs | 7 + src/xds-descriptors.bin | Bin 1342906 -> 1387951 bytes tests/generate_sources.rs | 3 +- tests/test_any.rs | 2 +- tests/test_pbjson.rs | 2 +- tests/test_value.rs | 2 +- 98 files changed, 8193 insertions(+), 6091 deletions(-) create mode 100644 src/generated/envoy.service.network_ext_proc.v3.rs create mode 100644 src/generated/envoy.service.network_ext_proc.v3.serde.rs rename src/generated/{envoy.service.trace.v3.rs => envoy.service.redis_auth.v3.rs} (64%) create mode 100644 src/generated/envoy.service.redis_auth.v3.serde.rs delete mode 100644 src/generated/envoy.service.trace.v3.serde.rs delete mode 100644 src/generated/opencensus.proto.resource.v1.rs delete mode 100644 src/generated/opencensus.proto.resource.v1.serde.rs delete mode 100644 src/generated/opencensus.proto.trace.v1.rs delete mode 100644 src/generated/opencensus.proto.trace.v1.serde.rs diff --git a/.protoc-version b/.protoc-version index 383283e..5c1a3ae 100644 --- a/.protoc-version +++ b/.protoc-version @@ -1 +1 @@ -27.3 +31.1 diff --git a/Cargo.lock b/Cargo.lock index 977dd3b..17ba112 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -171,12 +171,13 @@ checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "getrandom" -version = "0.2.15" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", + "r-efi", "wasi", ] @@ -470,22 +471,27 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" -version = "0.8.5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ - "libc", "rand_chacha", "rand_core", ] [[package]] name = "rand_chacha" -version = "0.3.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", "rand_core", @@ -493,9 +499,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ "getrandom", ] @@ -682,9 +688,9 @@ dependencies = [ [[package]] name = "tonic" -version = "0.12.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9" dependencies = [ "async-trait", "base64 0.22.1", @@ -703,9 +709,9 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.12.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" +checksum = "eac6f67be712d12f0b41328db3137e0d0757645d8904b4cb7d51cd9c2279e847" dependencies = [ "prettyplease", "proc-macro2", @@ -766,9 +772,12 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] [[package]] name = "windows-sys" @@ -861,6 +870,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + [[package]] name = "xds-api" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index 3d2cdf1..42ba980 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ doctest = false [dependencies] enum-map = "2.7" prost = "0.13" -tonic = { version = "0.12", default-features = false, features = [ +tonic = { version = "0.13", default-features = false, features = [ "prost", "codegen", ] } @@ -31,6 +31,7 @@ serde = { version = "1.0", optional = true } [features] pbjson = ["dep:pbjson", "dep:serde"] descriptor = [] +generate_only = [] [dev-dependencies] anyhow = "1" @@ -38,11 +39,9 @@ glob = "0.3" pbjson-build = "0.7" prost-build = "0.13" prost-types = "0.13" -rand = "0.8" +rand = "0.9" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" toml = "0.8" -tonic-build = { version = "0.12", default-features = false, features = [ - "prost", -] } +tonic-build = { version = "0.13", default-features = false, features = ["prost"] } xshell = "0.2" diff --git a/protobufs.toml b/protobufs.toml index cd445e1..14fa3b8 100644 --- a/protobufs.toml +++ b/protobufs.toml @@ -4,9 +4,9 @@ # the other dependencies in this file. The git refs here MUST match the versions # listed in enovyproxy/data-plane-api.git/bazel/repository_locations.bzl. [dependencies] -envoy-data-plane = { repo_url = "https://github.com/envoyproxy/data-plane-api.git", git_ref = "786c93ccaae9891338f098a5aba60e9987d78bd3" } -cncf-xds = { repo_url = "https://github.com/cncf/xds", git_ref = "555b57ec207be86f811fb0c04752db6f85e3d7e2" } +envoy-data-plane = { repo_url = "https://github.com/envoyproxy/data-plane-api.git", git_ref = "09409f495015a2a144d421300458d3ad49e20031" } +cncf-xds = { repo_url = "https://github.com/cncf/xds", git_ref = "2ac532fd44436293585084f8d94c6bdb17835af0" } protoc-gen-validate = { repo_url = "https://github.com/bufbuild/protoc-gen-validate", git_ref = "v1.0.4" } -googleapis = { repo_url = "https://github.com/googleapis/googleapis", git_ref = "114a745b2841a044e98cdbb19358ed29fcf4a5f1" } -opencensus-proto = { repo_url = "https://github.com/census-instrumentation/opencensus-proto", git_ref = "v0.4.1", proto_root = "src" } -prometheus-client-model = { repo_url = "https://github.com/prometheus/client_model", git_ref = "v0.6.1" } +googleapis = { repo_url = "https://github.com/googleapis/googleapis", git_ref = "fd52b5754b2b268bc3a22a10f29844f206abb327" } +opentelemetry-proto = { repo_url = "https://github.com/open-telemetry/opentelemetry-proto", git_ref = "v1.7.0", proto_root = "src" } +prometheus-client-model = { repo_url = "https://github.com/prometheus/client_model", git_ref = "v0.6.2" } diff --git a/src/generated/envoy.admin.v3.rs b/src/generated/envoy.admin.v3.rs index 11518b2..1e7802d 100644 --- a/src/generated/envoy.admin.v3.rs +++ b/src/generated/envoy.admin.v3.rs @@ -647,6 +647,12 @@ pub enum ClientResourceStatus { Acked = 3, /// Client received this resource and replied with NACK. Nacked = 4, + /// Client received an error from the control plane. The attached config + /// dump is the most recent accepted one. If no config is accepted yet, + /// the attached config dump will be empty. + ReceivedError = 5, + /// Client timed out waiting for the resource from the control plane. + Timeout = 6, } impl ClientResourceStatus { /// String value of the enum field names used in the ProtoBuf definition. @@ -660,6 +666,8 @@ impl ClientResourceStatus { Self::DoesNotExist => "DOES_NOT_EXIST", Self::Acked => "ACKED", Self::Nacked => "NACKED", + Self::ReceivedError => "RECEIVED_ERROR", + Self::Timeout => "TIMEOUT", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -670,6 +678,8 @@ impl ClientResourceStatus { "DOES_NOT_EXIST" => Some(Self::DoesNotExist), "ACKED" => Some(Self::Acked), "NACKED" => Some(Self::Nacked), + "RECEIVED_ERROR" => Some(Self::ReceivedError), + "TIMEOUT" => Some(Self::Timeout), _ => None, } } diff --git a/src/generated/envoy.admin.v3.serde.rs b/src/generated/envoy.admin.v3.serde.rs index 4ea224f..c372f37 100644 --- a/src/generated/envoy.admin.v3.serde.rs +++ b/src/generated/envoy.admin.v3.serde.rs @@ -10,6 +10,8 @@ impl serde::Serialize for ClientResourceStatus { Self::DoesNotExist => "DOES_NOT_EXIST", Self::Acked => "ACKED", Self::Nacked => "NACKED", + Self::ReceivedError => "RECEIVED_ERROR", + Self::Timeout => "TIMEOUT", }; serializer.serialize_str(variant) } @@ -26,6 +28,8 @@ impl<'de> serde::Deserialize<'de> for ClientResourceStatus { "DOES_NOT_EXIST", "ACKED", "NACKED", + "RECEIVED_ERROR", + "TIMEOUT", ]; struct GeneratedVisitor; @@ -71,6 +75,8 @@ impl<'de> serde::Deserialize<'de> for ClientResourceStatus { "DOES_NOT_EXIST" => Ok(ClientResourceStatus::DoesNotExist), "ACKED" => Ok(ClientResourceStatus::Acked), "NACKED" => Ok(ClientResourceStatus::Nacked), + "RECEIVED_ERROR" => Ok(ClientResourceStatus::ReceivedError), + "TIMEOUT" => Ok(ClientResourceStatus::Timeout), _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), } } diff --git a/src/generated/envoy.config.accesslog.v3.rs b/src/generated/envoy.config.accesslog.v3.rs index 5e6c0b8..744baeb 100644 --- a/src/generated/envoy.config.accesslog.v3.rs +++ b/src/generated/envoy.config.accesslog.v3.rs @@ -227,35 +227,38 @@ impl ::prost::Name for TraceableFilter { "type.googleapis.com/envoy.config.accesslog.v3.TraceableFilter".into() } } -/// Filters for random sampling of requests. +/// Filters requests based on runtime-configurable sampling rates. #[derive(Clone, PartialEq, ::prost::Message)] pub struct RuntimeFilter { - /// Runtime key to get an optional overridden numerator for use in the - /// ``percent_sampled`` field. If found in runtime, this value will replace the - /// default numerator. + /// Specifies a key used to look up a custom sampling rate from the runtime configuration. If a value is found for this + /// key, it will override the default sampling rate specified in ``percent_sampled``. #[prost(string, tag = "1")] pub runtime_key: ::prost::alloc::string::String, - /// The default sampling percentage. If not specified, defaults to 0% with - /// denominator of 100. + /// Defines the default sampling percentage when no runtime override is present. If not specified, the default is + /// **0%** (with a denominator of 100). #[prost(message, optional, tag = "2")] pub percent_sampled: ::core::option::Option< super::super::super::r#type::v3::FractionalPercent, >, - /// By default, sampling pivots on the header - /// :ref:`x-request-id` being - /// present. If :ref:`x-request-id` - /// is present, the filter will consistently sample across multiple hosts based - /// on the runtime key value and the value extracted from - /// :ref:`x-request-id`. If it is - /// missing, or ``use_independent_randomness`` is set to true, the filter will - /// randomly sample based on the runtime key value alone. - /// ``use_independent_randomness`` can be used for logging kill switches within - /// complex nested :ref:`AndFilter - /// ` and :ref:`OrFilter - /// ` blocks that are easier to - /// reason about from a probability perspective (i.e., setting to true will - /// cause the filter to behave like an independent random variable when - /// composed within logical operator filters). + /// Controls how sampling decisions are made. + /// + /// - Default behavior (``false``): + /// + /// * Uses the :ref:`x-request-id` as a consistent sampling pivot. + /// * When :ref:`x-request-id` is present, sampling will be consistent + /// across multiple hosts based on both the ``runtime_key`` and + /// :ref:`x-request-id`. + /// * Useful for tracking related requests across a distributed system. + /// + /// - When set to ``true`` or :ref:`x-request-id` is missing: + /// + /// * Sampling decisions are made randomly based only on the ``runtime_key``. + /// * Useful in complex filter configurations (like nested + /// :ref:`AndFilter`/ + /// :ref:`OrFilter` blocks) where independent probability + /// calculations are desired. + /// * Can be used to implement logging kill switches with predictable probability distributions. + /// #[prost(bool, tag = "3")] pub use_independent_randomness: bool, } diff --git a/src/generated/envoy.config.bootstrap.v3.rs b/src/generated/envoy.config.bootstrap.v3.rs index 2a67118..a85a6f6 100644 --- a/src/generated/envoy.config.bootstrap.v3.rs +++ b/src/generated/envoy.config.bootstrap.v3.rs @@ -299,9 +299,7 @@ pub mod bootstrap { /// If a network based configuration source is specified for :ref:`cds_config /// `, it's necessary /// to have some initial cluster definitions available to allow Envoy to know - /// how to speak to the management server. These cluster definitions may not - /// use :ref:`EDS ` (i.e. they should be static - /// IP or DNS-based). + /// how to speak to the management server. #[prost(message, repeated, tag = "2")] pub clusters: ::prost::alloc::vec::Vec< super::super::super::cluster::v3::Cluster, diff --git a/src/generated/envoy.config.cluster.v3.rs b/src/generated/envoy.config.cluster.v3.rs index 065441c..20a2bd6 100644 --- a/src/generated/envoy.config.cluster.v3.rs +++ b/src/generated/envoy.config.cluster.v3.rs @@ -184,7 +184,7 @@ impl ::prost::Name for Filter { } /// See the :ref:`architecture overview ` for /// more information on outlier detection. -/// \[#next-free-field: 25\] +/// \[#next-free-field: 26\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct OutlierDetection { /// The number of consecutive server-side error responses (for HTTP traffic, @@ -209,8 +209,8 @@ pub struct OutlierDetection { pub base_ejection_time: ::core::option::Option< super::super::super::super::google::protobuf::Duration, >, - /// The maximum % of an upstream cluster that can be ejected due to outlier - /// detection. Defaults to 10% but will eject at least one host regardless of the value. + /// The maximum % of an upstream cluster that can be ejected due to outlier detection. Defaults to 10% . + /// Will eject at least one host regardless of the value if :ref:`always_eject_one_host` is enabled. #[prost(message, optional, tag = "4")] pub max_ejection_percent: ::core::option::Option< super::super::super::super::google::protobuf::UInt32Value, @@ -373,6 +373,12 @@ pub struct OutlierDetection { /// \[#not-implemented-hide:\] #[prost(message, repeated, tag = "24")] pub monitors: ::prost::alloc::vec::Vec, + /// If enabled, at least one host is ejected regardless of the value of :ref:`max_ejection_percent`. + /// Defaults to false. + #[prost(message, optional, tag = "25")] + pub always_eject_one_host: ::core::option::Option< + super::super::super::super::google::protobuf::BoolValue, + >, } impl ::prost::Name for OutlierDetection { const NAME: &'static str = "OutlierDetection"; @@ -404,15 +410,17 @@ impl ::prost::Name for ClusterCollection { } } /// Configuration for a single upstream cluster. -/// \[#next-free-field: 57\] +/// \[#next-free-field: 59\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Cluster { - /// Configuration to use different transport sockets for different endpoints. - /// The entry of ``envoy.transport_socket_match`` in the - /// :ref:`LbEndpoint.Metadata ` - /// is used to match against the transport sockets as they appear in the list. The first - /// :ref:`match ` is used. - /// For example, with the following match + /// Configuration to use different transport sockets for different endpoints. The entry of + /// ``envoy.transport_socket_match`` in the :ref:`LbEndpoint.Metadata + /// ` is used to match against the + /// transport sockets as they appear in the list. If a match is not found, the search continues in + /// :ref:`LocalityLbEndpoints.Metadata + /// `. The first :ref:`match + /// ` is used. For example, with + /// the following match /// /// .. code-block:: yaml /// @@ -436,8 +444,9 @@ pub struct Cluster { /// socket match in case above. /// /// If an endpoint metadata's value under ``envoy.transport_socket_match`` does not match any - /// ``TransportSocketMatch``, socket configuration fallbacks to use the ``tls_context`` or - /// ``transport_socket`` specified in this cluster. + /// ``TransportSocketMatch``, the locality metadata is then checked for a match. Barring any + /// matches in the endpoint or locality metadata, the socket configuration fallbacks to use the + /// ``tls_context`` or ``transport_socket`` specified in this cluster. /// /// This field allows gradual and flexible transport socket configuration changes. /// @@ -468,12 +477,14 @@ pub struct Cluster { #[prost(string, tag = "1")] pub name: ::prost::alloc::string::String, /// An optional alternative to the cluster name to be used for observability. This name is used - /// emitting stats for the cluster and access logging the cluster name. This will appear as + /// for emitting stats for the cluster and access logging the cluster name. This will appear as /// additional information in configuration dumps of a cluster's current status as /// :ref:`observability_name ` - /// and as an additional tag "upstream_cluster.name" while tracing. Note: Any ``:`` in the name - /// will be converted to ``_`` when emitting statistics. This should not be confused with - /// :ref:`Router Filter Header `. + /// and as an additional tag "upstream_cluster.name" while tracing. + /// + /// .. note:: + /// Any ``:`` in the name will be converted to ``_`` when emitting statistics. This should not be confused with + /// :ref:`Router Filter Header `. #[prost(string, tag = "28")] pub alt_stat_name: ::prost::alloc::string::String, /// Configuration to use for EDS updates for the Cluster. @@ -597,6 +608,7 @@ pub struct Cluster { /// "envoy.filters.network.thrift_proxy". See the extension's documentation for details on /// specific options. /// \[#next-major-version: make this a list of typed extensions.\] + /// \[#extension-category: envoy.upstream_options\] #[prost(map = "string, message", tag = "36")] pub typed_extension_protocol_options: ::std::collections::HashMap< ::prost::alloc::string::String, @@ -611,10 +623,33 @@ pub struct Cluster { /// :ref:`STRICT_DNS` /// and :ref:`LOGICAL_DNS` /// this setting is ignored. + /// This field is deprecated in favor of using the :ref:`cluster_type` + /// extension point and configuring it with :ref:`DnsCluster`. + /// If :ref:`cluster_type` is configured with + /// :ref:`DnsCluster`, this field will be ignored. + #[deprecated] #[prost(message, optional, tag = "16")] pub dns_refresh_rate: ::core::option::Option< super::super::super::super::google::protobuf::Duration, >, + /// DNS jitter can be optionally specified if the cluster type is either + /// :ref:`STRICT_DNS`, + /// or :ref:`LOGICAL_DNS`. + /// DNS jitter causes the cluster to refresh DNS entries later by a random amount of time to avoid a + /// stampede of DNS requests. This value sets the upper bound (exclusive) for the random amount. + /// There will be no jitter if this value is omitted. For cluster types other than + /// :ref:`STRICT_DNS` + /// and :ref:`LOGICAL_DNS` + /// this setting is ignored. + /// This field is deprecated in favor of using the :ref:`cluster_type` + /// extension point and configuring it with :ref:`DnsCluster`. + /// If :ref:`cluster_type` is configured with + /// :ref:`DnsCluster`, this field will be ignored. + #[deprecated] + #[prost(message, optional, tag = "58")] + pub dns_jitter: ::core::option::Option< + super::super::super::super::google::protobuf::Duration, + >, /// If the DNS failure refresh rate is specified and the cluster type is either /// :ref:`STRICT_DNS`, /// or :ref:`LOGICAL_DNS`, @@ -623,16 +658,31 @@ pub struct Cluster { /// other than :ref:`STRICT_DNS` and /// :ref:`LOGICAL_DNS` this setting is /// ignored. + /// This field is deprecated in favor of using the :ref:`cluster_type` + /// extension point and configuring it with :ref:`DnsCluster`. + /// If :ref:`cluster_type` is configured with + /// :ref:`DnsCluster`, this field will be ignored. + #[deprecated] #[prost(message, optional, tag = "44")] pub dns_failure_refresh_rate: ::core::option::Option, /// Optional configuration for setting cluster's DNS refresh rate. If the value is set to true, /// cluster's DNS refresh rate will be set to resource record's TTL which comes from DNS /// resolution. + /// This field is deprecated in favor of using the :ref:`cluster_type` + /// extension point and configuring it with :ref:`DnsCluster`. + /// If :ref:`cluster_type` is configured with + /// :ref:`DnsCluster`, this field will be ignored. + #[deprecated] #[prost(bool, tag = "39")] pub respect_dns_ttl: bool, /// The DNS IP address resolution policy. If this setting is not specified, the /// value defaults to /// :ref:`AUTO`. + /// For logical and strict dns cluster, this field is deprecated in favor of using the + /// :ref:`cluster_type` + /// extension point and configuring it with :ref:`DnsCluster`. + /// If :ref:`cluster_type` is configured with + /// :ref:`DnsCluster`, this field will be ignored. #[prost(enumeration = "cluster::DnsLookupFamily", tag = "17")] pub dns_lookup_family: i32, /// If DNS resolvers are specified and the cluster type is either @@ -674,6 +724,9 @@ pub struct Cluster { /// During the transition period when both ``dns_resolution_config`` and ``typed_dns_resolver_config`` exists, /// when ``typed_dns_resolver_config`` is in place, Envoy will use it and ignore ``dns_resolution_config``. /// When ``typed_dns_resolver_config`` is missing, the default behavior is in place. + /// Also note that this field is deprecated for logical dns and strict dns clusters and will be ignored when + /// :ref:`cluster_type` is configured with + /// :ref:`DnsCluster`. /// \[#extension-category: envoy.network.dns_resolver\] #[prost(message, optional, tag = "55")] pub typed_dns_resolver_config: ::core::option::Option< @@ -795,6 +848,25 @@ pub struct Cluster { /// from the LRS stream here.] #[prost(message, optional, tag = "42")] pub lrs_server: ::core::option::Option, + /// A list of metric names from :ref:`ORCA load reports ` to propagate to LRS. + /// + /// If not specified, then ORCA load reports will not be propagated to LRS. + /// + /// For map fields in the ORCA proto, the string will be of the form ``.``. + /// For example, the string ``named_metrics.foo`` will mean to look for the key ``foo`` in the ORCA + /// :ref:`named_metrics ` field. + /// + /// The special map key ``*`` means to report all entries in the map (e.g., ``named_metrics.*`` means to + /// report all entries in the ORCA named_metrics field). Note that this should be used only with trusted + /// backends. + /// + /// The metric names in LRS will follow the same semantics as this field. In other words, if this field + /// contains ``named_metrics.foo``, then the LRS load report will include the data with that same string + /// as the key. + #[prost(string, repeated, tag = "57")] + pub lrs_report_endpoint_metrics: ::prost::alloc::vec::Vec< + ::prost::alloc::string::String, + >, /// If track_timeout_budgets is true, the :ref:`timeout budget histograms /// ` will be published for each /// request. These show what percentage of a request's per try and global timeout was used. A value @@ -862,7 +934,7 @@ pub mod cluster { /// The name of the match, used in stats generation. #[prost(string, tag = "1")] pub name: ::prost::alloc::string::String, - /// Optional endpoint metadata match criteria. + /// Optional metadata match criteria. /// The connection to the endpoint with metadata matching what is set in this field /// will use the transport socket configuration specified here. /// The endpoint's metadata entry in ``envoy.transport_socket_match`` is used to match @@ -1553,9 +1625,10 @@ pub mod cluster { /// If this is not set, we default to a merge window of 1000ms. To disable it, set the merge /// window to 0. /// - /// Note: merging does not apply to cluster membership changes (e.g.: adds/removes); this is - /// because merging those updates isn't currently safe. See - /// + /// .. note:: + /// Merging does not apply to cluster membership changes (e.g.: adds/removes); this is + /// because merging those updates isn't currently safe. See + /// #[prost(message, optional, tag = "4")] pub update_merge_window: ::core::option::Option< super::super::super::super::super::google::protobuf::Duration, @@ -2256,7 +2329,7 @@ pub struct TrackClusterStats { pub timeout_budgets: bool, /// If request_response_sizes is true, then the :ref:`histograms /// ` tracking header and body sizes - /// of requests and responses will be published. + /// of requests and responses will be published. Additionally, number of headers in the requests and responses will be tracked. #[prost(bool, tag = "2")] pub request_response_sizes: bool, /// If true, some stats will be emitted per-endpoint, similar to the stats in admin ``/clusters`` diff --git a/src/generated/envoy.config.cluster.v3.serde.rs b/src/generated/envoy.config.cluster.v3.serde.rs index 595aa2d..0a3c599 100644 --- a/src/generated/envoy.config.cluster.v3.serde.rs +++ b/src/generated/envoy.config.cluster.v3.serde.rs @@ -495,6 +495,9 @@ impl serde::Serialize for Cluster { if self.dns_refresh_rate.is_some() { len += 1; } + if self.dns_jitter.is_some() { + len += 1; + } if self.dns_failure_refresh_rate.is_some() { len += 1; } @@ -561,6 +564,9 @@ impl serde::Serialize for Cluster { if self.lrs_server.is_some() { len += 1; } + if !self.lrs_report_endpoint_metrics.is_empty() { + len += 1; + } if self.track_timeout_budgets { len += 1; } @@ -636,6 +642,9 @@ impl serde::Serialize for Cluster { if let Some(v) = self.dns_refresh_rate.as_ref() { struct_ser.serialize_field("dns_refresh_rate", v)?; } + if let Some(v) = self.dns_jitter.as_ref() { + struct_ser.serialize_field("dns_jitter", v)?; + } if let Some(v) = self.dns_failure_refresh_rate.as_ref() { struct_ser.serialize_field("dns_failure_refresh_rate", v)?; } @@ -706,6 +715,9 @@ impl serde::Serialize for Cluster { if let Some(v) = self.lrs_server.as_ref() { struct_ser.serialize_field("lrs_server", v)?; } + if !self.lrs_report_endpoint_metrics.is_empty() { + struct_ser.serialize_field("lrs_report_endpoint_metrics", &self.lrs_report_endpoint_metrics)?; + } if self.track_timeout_budgets { struct_ser.serialize_field("track_timeout_budgets", &self.track_timeout_budgets)?; } @@ -795,6 +807,8 @@ impl<'de> serde::Deserialize<'de> for Cluster { "typedExtensionProtocolOptions", "dns_refresh_rate", "dnsRefreshRate", + "dns_jitter", + "dnsJitter", "dns_failure_refresh_rate", "dnsFailureRefreshRate", "respect_dns_ttl", @@ -837,6 +851,8 @@ impl<'de> serde::Deserialize<'de> for Cluster { "loadBalancingPolicy", "lrs_server", "lrsServer", + "lrs_report_endpoint_metrics", + "lrsReportEndpointMetrics", "track_timeout_budgets", "trackTimeoutBudgets", "upstream_config", @@ -881,6 +897,7 @@ impl<'de> serde::Deserialize<'de> for Cluster { Http2ProtocolOptions, TypedExtensionProtocolOptions, DnsRefreshRate, + DnsJitter, DnsFailureRefreshRate, RespectDnsTtl, DnsLookupFamily, @@ -903,6 +920,7 @@ impl<'de> serde::Deserialize<'de> for Cluster { Filters, LoadBalancingPolicy, LrsServer, + LrsReportEndpointMetrics, TrackTimeoutBudgets, UpstreamConfig, TrackClusterStats, @@ -953,6 +971,7 @@ impl<'de> serde::Deserialize<'de> for Cluster { "http2ProtocolOptions" | "http2_protocol_options" => Ok(GeneratedField::Http2ProtocolOptions), "typedExtensionProtocolOptions" | "typed_extension_protocol_options" => Ok(GeneratedField::TypedExtensionProtocolOptions), "dnsRefreshRate" | "dns_refresh_rate" => Ok(GeneratedField::DnsRefreshRate), + "dnsJitter" | "dns_jitter" => Ok(GeneratedField::DnsJitter), "dnsFailureRefreshRate" | "dns_failure_refresh_rate" => Ok(GeneratedField::DnsFailureRefreshRate), "respectDnsTtl" | "respect_dns_ttl" => Ok(GeneratedField::RespectDnsTtl), "dnsLookupFamily" | "dns_lookup_family" => Ok(GeneratedField::DnsLookupFamily), @@ -975,6 +994,7 @@ impl<'de> serde::Deserialize<'de> for Cluster { "filters" => Ok(GeneratedField::Filters), "loadBalancingPolicy" | "load_balancing_policy" => Ok(GeneratedField::LoadBalancingPolicy), "lrsServer" | "lrs_server" => Ok(GeneratedField::LrsServer), + "lrsReportEndpointMetrics" | "lrs_report_endpoint_metrics" => Ok(GeneratedField::LrsReportEndpointMetrics), "trackTimeoutBudgets" | "track_timeout_budgets" => Ok(GeneratedField::TrackTimeoutBudgets), "upstreamConfig" | "upstream_config" => Ok(GeneratedField::UpstreamConfig), "trackClusterStats" | "track_cluster_stats" => Ok(GeneratedField::TrackClusterStats), @@ -1023,6 +1043,7 @@ impl<'de> serde::Deserialize<'de> for Cluster { let mut http2_protocol_options__ = None; let mut typed_extension_protocol_options__ = None; let mut dns_refresh_rate__ = None; + let mut dns_jitter__ = None; let mut dns_failure_refresh_rate__ = None; let mut respect_dns_ttl__ = None; let mut dns_lookup_family__ = None; @@ -1045,6 +1066,7 @@ impl<'de> serde::Deserialize<'de> for Cluster { let mut filters__ = None; let mut load_balancing_policy__ = None; let mut lrs_server__ = None; + let mut lrs_report_endpoint_metrics__ = None; let mut track_timeout_budgets__ = None; let mut upstream_config__ = None; let mut track_cluster_stats__ = None; @@ -1158,6 +1180,12 @@ impl<'de> serde::Deserialize<'de> for Cluster { } dns_refresh_rate__ = map_.next_value()?; } + GeneratedField::DnsJitter => { + if dns_jitter__.is_some() { + return Err(serde::de::Error::duplicate_field("dnsJitter")); + } + dns_jitter__ = map_.next_value()?; + } GeneratedField::DnsFailureRefreshRate => { if dns_failure_refresh_rate__.is_some() { return Err(serde::de::Error::duplicate_field("dnsFailureRefreshRate")); @@ -1290,6 +1318,12 @@ impl<'de> serde::Deserialize<'de> for Cluster { } lrs_server__ = map_.next_value()?; } + GeneratedField::LrsReportEndpointMetrics => { + if lrs_report_endpoint_metrics__.is_some() { + return Err(serde::de::Error::duplicate_field("lrsReportEndpointMetrics")); + } + lrs_report_endpoint_metrics__ = Some(map_.next_value()?); + } GeneratedField::TrackTimeoutBudgets => { if track_timeout_budgets__.is_some() { return Err(serde::de::Error::duplicate_field("trackTimeoutBudgets")); @@ -1388,6 +1422,7 @@ impl<'de> serde::Deserialize<'de> for Cluster { http2_protocol_options: http2_protocol_options__, typed_extension_protocol_options: typed_extension_protocol_options__.unwrap_or_default(), dns_refresh_rate: dns_refresh_rate__, + dns_jitter: dns_jitter__, dns_failure_refresh_rate: dns_failure_refresh_rate__, respect_dns_ttl: respect_dns_ttl__.unwrap_or_default(), dns_lookup_family: dns_lookup_family__.unwrap_or_default(), @@ -1410,6 +1445,7 @@ impl<'de> serde::Deserialize<'de> for Cluster { filters: filters__.unwrap_or_default(), load_balancing_policy: load_balancing_policy__, lrs_server: lrs_server__, + lrs_report_endpoint_metrics: lrs_report_endpoint_metrics__.unwrap_or_default(), track_timeout_budgets: track_timeout_budgets__.unwrap_or_default(), upstream_config: upstream_config__, track_cluster_stats: track_cluster_stats__, @@ -4694,6 +4730,9 @@ impl serde::Serialize for OutlierDetection { if !self.monitors.is_empty() { len += 1; } + if self.always_eject_one_host.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.config.cluster.v3.OutlierDetection", len)?; if let Some(v) = self.consecutive_5xx.as_ref() { struct_ser.serialize_field("consecutive_5xx", v)?; @@ -4767,6 +4806,9 @@ impl serde::Serialize for OutlierDetection { if !self.monitors.is_empty() { struct_ser.serialize_field("monitors", &self.monitors)?; } + if let Some(v) = self.always_eject_one_host.as_ref() { + struct_ser.serialize_field("always_eject_one_host", v)?; + } struct_ser.end() } } @@ -4823,6 +4865,8 @@ impl<'de> serde::Deserialize<'de> for OutlierDetection { "successful_active_health_check_uneject_host", "successfulActiveHealthCheckUnejectHost", "monitors", + "always_eject_one_host", + "alwaysEjectOneHost", ]; #[allow(clippy::enum_variant_names)] @@ -4851,6 +4895,7 @@ impl<'de> serde::Deserialize<'de> for OutlierDetection { MaxEjectionTimeJitter, SuccessfulActiveHealthCheckUnejectHost, Monitors, + AlwaysEjectOneHost, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -4896,6 +4941,7 @@ impl<'de> serde::Deserialize<'de> for OutlierDetection { "maxEjectionTimeJitter" | "max_ejection_time_jitter" => Ok(GeneratedField::MaxEjectionTimeJitter), "successfulActiveHealthCheckUnejectHost" | "successful_active_health_check_uneject_host" => Ok(GeneratedField::SuccessfulActiveHealthCheckUnejectHost), "monitors" => Ok(GeneratedField::Monitors), + "alwaysEjectOneHost" | "always_eject_one_host" => Ok(GeneratedField::AlwaysEjectOneHost), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -4939,6 +4985,7 @@ impl<'de> serde::Deserialize<'de> for OutlierDetection { let mut max_ejection_time_jitter__ = None; let mut successful_active_health_check_uneject_host__ = None; let mut monitors__ = None; + let mut always_eject_one_host__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Consecutive5xx => { @@ -5085,6 +5132,12 @@ impl<'de> serde::Deserialize<'de> for OutlierDetection { } monitors__ = Some(map_.next_value()?); } + GeneratedField::AlwaysEjectOneHost => { + if always_eject_one_host__.is_some() { + return Err(serde::de::Error::duplicate_field("alwaysEjectOneHost")); + } + always_eject_one_host__ = map_.next_value()?; + } } } Ok(OutlierDetection { @@ -5112,6 +5165,7 @@ impl<'de> serde::Deserialize<'de> for OutlierDetection { max_ejection_time_jitter: max_ejection_time_jitter__, successful_active_health_check_uneject_host: successful_active_health_check_uneject_host__, monitors: monitors__.unwrap_or_default(), + always_eject_one_host: always_eject_one_host__, }) } } diff --git a/src/generated/envoy.config.common.matcher.v3.rs b/src/generated/envoy.config.common.matcher.v3.rs index 4b0b3b6..47570ab 100644 --- a/src/generated/envoy.config.common.matcher.v3.rs +++ b/src/generated/envoy.config.common.matcher.v3.rs @@ -9,8 +9,8 @@ /// Please use the syntactically equivalent :ref:`matching API ` #[derive(Clone, PartialEq, ::prost::Message)] pub struct Matcher { - /// Optional OnMatch to use if the matcher failed. - /// If specified, the OnMatch is used, and the matcher is considered + /// Optional ``OnMatch`` to use if the matcher failed. + /// If specified, the ``OnMatch`` is used, and the matcher is considered /// to have matched. /// If not specified, the matcher is considered not to have matched. #[prost(message, optional, boxed, tag = "3")] @@ -25,6 +25,17 @@ pub mod matcher { /// What to do if a match is successful. #[derive(Clone, PartialEq, ::prost::Message)] pub struct OnMatch { + /// If true, the action will be taken but the caller will behave as if no + /// match was found. This applies both to actions directly encoded in the + /// action field and to actions returned from a nested matcher tree in the + /// matcher field. A subsequent matcher on_no_match action will be used + /// instead. + /// + /// This field is not supported in all contexts in which the matcher API is + /// used. If this field is set in a context in which it's not supported, + /// the resource will be rejected. + #[prost(bool, tag = "3")] + pub keep_matching: bool, #[prost(oneof = "on_match::OnMatch", tags = "1, 2")] pub on_match: ::core::option::Option, } @@ -143,7 +154,7 @@ pub mod matcher { /// A list of predicates to be AND-ed together. #[prost(message, tag = "3")] AndMatcher(PredicateList), - /// The invert of a predicate + /// The inverse of a predicate #[prost(message, tag = "4")] NotMatcher(::prost::alloc::boxed::Box), } @@ -373,9 +384,9 @@ impl ::prost::Name for HttpHeadersMatch { /// /// .. attention:: /// -/// Searching for patterns in HTTP body is potentially cpu intensive. For each specified pattern, http body is scanned byte by byte to find a match. +/// Searching for patterns in HTTP body is potentially CPU-intensive. For each specified pattern, HTTP body is scanned byte by byte to find a match. /// If multiple patterns are specified, the process is repeated for each pattern. If location of a pattern is known, ``bytes_limit`` should be specified -/// to scan only part of the http body. +/// to scan only part of the HTTP body. #[derive(Clone, PartialEq, ::prost::Message)] pub struct HttpGenericBodyMatch { /// Limits search to specified number of bytes - default zero (no limit - match entire captured buffer). diff --git a/src/generated/envoy.config.common.matcher.v3.serde.rs b/src/generated/envoy.config.common.matcher.v3.serde.rs index 50e90d2..a9e07ed 100644 --- a/src/generated/envoy.config.common.matcher.v3.serde.rs +++ b/src/generated/envoy.config.common.matcher.v3.serde.rs @@ -1554,10 +1554,16 @@ impl serde::Serialize for matcher::OnMatch { { use serde::ser::SerializeStruct; let mut len = 0; + if self.keep_matching { + len += 1; + } if self.on_match.is_some() { len += 1; } let mut struct_ser = serializer.serialize_struct("envoy.config.common.matcher.v3.Matcher.OnMatch", len)?; + if self.keep_matching { + struct_ser.serialize_field("keep_matching", &self.keep_matching)?; + } if let Some(v) = self.on_match.as_ref() { match v { matcher::on_match::OnMatch::Matcher(v) => { @@ -1578,12 +1584,15 @@ impl<'de> serde::Deserialize<'de> for matcher::OnMatch { D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ + "keep_matching", + "keepMatching", "matcher", "action", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { + KeepMatching, Matcher, Action, } @@ -1607,6 +1616,7 @@ impl<'de> serde::Deserialize<'de> for matcher::OnMatch { E: serde::de::Error, { match value { + "keepMatching" | "keep_matching" => Ok(GeneratedField::KeepMatching), "matcher" => Ok(GeneratedField::Matcher), "action" => Ok(GeneratedField::Action), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), @@ -1628,9 +1638,16 @@ impl<'de> serde::Deserialize<'de> for matcher::OnMatch { where V: serde::de::MapAccess<'de>, { + let mut keep_matching__ = None; let mut on_match__ = None; while let Some(k) = map_.next_key()? { match k { + GeneratedField::KeepMatching => { + if keep_matching__.is_some() { + return Err(serde::de::Error::duplicate_field("keepMatching")); + } + keep_matching__ = Some(map_.next_value()?); + } GeneratedField::Matcher => { if on_match__.is_some() { return Err(serde::de::Error::duplicate_field("matcher")); @@ -1648,6 +1665,7 @@ impl<'de> serde::Deserialize<'de> for matcher::OnMatch { } } Ok(matcher::OnMatch { + keep_matching: keep_matching__.unwrap_or_default(), on_match: on_match__, }) } diff --git a/src/generated/envoy.config.core.v3.rs b/src/generated/envoy.config.core.v3.rs index a58e3cb..1cbdf30 100644 --- a/src/generated/envoy.config.core.v3.rs +++ b/src/generated/envoy.config.core.v3.rs @@ -50,7 +50,7 @@ impl ::prost::Name for TypedExtensionConfig { /// :ref:`admin's ` socket_options etc. /// /// It should be noted that the name or level may have different values on different platforms. -/// \[#next-free-field: 7\] +/// \[#next-free-field: 8\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct SocketOption { /// An optional name to give this socket option for debugging, etc. @@ -67,11 +67,72 @@ pub struct SocketOption { /// STATE_PREBIND is currently the only valid value. #[prost(enumeration = "socket_option::SocketState", tag = "6")] pub state: i32, + /// Apply the socket option to the specified `socket type <`_.> + /// If not specified, the socket option will be applied to all socket types. + #[prost(message, optional, tag = "7")] + pub r#type: ::core::option::Option, #[prost(oneof = "socket_option::Value", tags = "4, 5")] pub value: ::core::option::Option, } /// Nested message and enum types in `SocketOption`. pub mod socket_option { + /// The `socket type <`_> to apply the socket option to. + /// Only one field should be set. If multiple fields are set, the precedence order will determine + /// the selected one. If none of the fields is set, the socket option will be applied to all socket types. + /// + /// For example: + /// If :ref:`stream ` is set, + /// it takes precedence over :ref:`datagram `. + #[derive(Clone, Copy, PartialEq, ::prost::Message)] + pub struct SocketType { + /// Apply the socket option to the stream socket type. + #[prost(message, optional, tag = "1")] + pub stream: ::core::option::Option, + /// Apply the socket option to the datagram socket type. + #[prost(message, optional, tag = "2")] + pub datagram: ::core::option::Option, + } + /// Nested message and enum types in `SocketType`. + pub mod socket_type { + /// The stream socket type. + #[derive(Clone, Copy, PartialEq, ::prost::Message)] + pub struct Stream {} + impl ::prost::Name for Stream { + const NAME: &'static str = "Stream"; + const PACKAGE: &'static str = "envoy.config.core.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.config.core.v3.SocketOption.SocketType.Stream".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.config.core.v3.SocketOption.SocketType.Stream" + .into() + } + } + /// The datagram socket type. + #[derive(Clone, Copy, PartialEq, ::prost::Message)] + pub struct Datagram {} + impl ::prost::Name for Datagram { + const NAME: &'static str = "Datagram"; + const PACKAGE: &'static str = "envoy.config.core.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.config.core.v3.SocketOption.SocketType.Datagram".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.config.core.v3.SocketOption.SocketType.Datagram" + .into() + } + } + } + impl ::prost::Name for SocketType { + const NAME: &'static str = "SocketType"; + const PACKAGE: &'static str = "envoy.config.core.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.config.core.v3.SocketOption.SocketType".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.config.core.v3.SocketOption.SocketType".into() + } + } #[derive( Clone, Copy, @@ -205,7 +266,7 @@ impl ::prost::Name for EnvoyInternalAddress { "type.googleapis.com/envoy.config.core.v3.EnvoyInternalAddress".into() } } -/// \[#next-free-field: 7\] +/// \[#next-free-field: 8\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct SocketAddress { #[prost(enumeration = "socket_address::Protocol", tag = "1")] @@ -236,6 +297,20 @@ pub struct SocketAddress { /// IPv6 space as ``::FFFF:``. #[prost(bool, tag = "6")] pub ipv4_compat: bool, + /// Filepath that specifies the Linux network namespace this socket will be created in (see ``man 7 + /// network_namespaces``). If this field is set, Envoy will create the socket in the specified + /// network namespace. + /// + /// .. note:: + /// Setting this parameter requires Envoy to run with the ``CAP_NET_ADMIN`` capability. + /// + /// .. note:: + /// Currently only used for Listener sockets. + /// + /// .. attention:: + /// Network namespaces are only configurable on Linux. Otherwise, this field has no effect. + #[prost(string, tag = "7")] + pub network_namespace_filepath: ::prost::alloc::string::String, #[prost(oneof = "socket_address::PortSpecifier", tags = "3, 4")] pub port_specifier: ::core::option::Option, } @@ -882,12 +957,21 @@ impl ::prost::Name for RuntimeFeatureFlag { "type.googleapis.com/envoy.config.core.v3.RuntimeFeatureFlag".into() } } +/// Please use :ref:`KeyValuePair ` instead. +/// \[#not-implemented-hide:\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct KeyValue { /// The key of the key/value pair. + #[deprecated] #[prost(string, tag = "1")] pub key: ::prost::alloc::string::String, /// The value of the key/value pair. + /// + /// The ``bytes`` type is used. This means if JSON or YAML is used to to represent the + /// configuration, the value must be base64 encoded. This is unfriendly for users in most + /// use scenarios of this message. + /// + #[deprecated] #[prost(bytes = "vec", tag = "2")] pub value: ::prost::alloc::vec::Vec, } @@ -901,11 +985,39 @@ impl ::prost::Name for KeyValue { "type.googleapis.com/envoy.config.core.v3.KeyValue".into() } } +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct KeyValuePair { + /// The key of the key/value pair. + #[prost(string, tag = "1")] + pub key: ::prost::alloc::string::String, + /// The value of the key/value pair. + #[prost(message, optional, tag = "2")] + pub value: ::core::option::Option< + super::super::super::super::google::protobuf::Value, + >, +} +impl ::prost::Name for KeyValuePair { + const NAME: &'static str = "KeyValuePair"; + const PACKAGE: &'static str = "envoy.config.core.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.config.core.v3.KeyValuePair".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.config.core.v3.KeyValuePair".into() + } +} /// Key/value pair plus option to control append behavior. This is used to specify /// key/value pairs that should be appended to a set of existing key/value pairs. #[derive(Clone, PartialEq, ::prost::Message)] pub struct KeyValueAppend { - /// Key/value pair entry that this option to append or overwrite. + /// The single key/value pair record to be appended or overridden. This field must be set. + #[prost(message, optional, tag = "3")] + pub record: ::core::option::Option, + /// Key/value pair entry that this option to append or overwrite. This field is deprecated + /// and please use :ref:`record ` + /// as replacement. + /// \[#not-implemented-hide:\] + #[deprecated] #[prost(message, optional, tag = "1")] pub entry: ::core::option::Option, /// Describes the action taken to append/overwrite the given value for an existing @@ -986,10 +1098,12 @@ impl ::prost::Name for KeyValueAppend { /// Key/value pair to append or remove. #[derive(Clone, PartialEq, ::prost::Message)] pub struct KeyValueMutation { - /// Key/value pair to append or overwrite. Only one of ``append`` or ``remove`` can be set. + /// Key/value pair to append or overwrite. Only one of ``append`` or ``remove`` can be set or + /// the configuration will be rejected. #[prost(message, optional, tag = "1")] pub append: ::core::option::Option, - /// Key to remove. Only one of ``append`` or ``remove`` can be set. + /// Key to remove. Only one of ``append`` or ``remove`` can be set or the configuration will be + /// rejected. #[prost(string, tag = "2")] pub remove: ::prost::alloc::string::String, } @@ -1156,6 +1270,7 @@ impl ::prost::Name for HeaderValueOption { /// Wrapper for a set of headers. #[derive(Clone, PartialEq, ::prost::Message)] pub struct HeaderMap { + /// A list of header names and their values. #[prost(message, repeated, tag = "1")] pub headers: ::prost::alloc::vec::Vec, } @@ -1651,6 +1766,26 @@ impl ::prost::Name for ProxyProtocolPassThroughTlVs { "type.googleapis.com/envoy.config.core.v3.ProxyProtocolPassThroughTLVs".into() } } +/// Represents a single Type-Length-Value (TLV) entry. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TlvEntry { + /// The type of the TLV. Must be a uint8 (0-255) as per the Proxy Protocol v2 specification. + #[prost(uint32, tag = "1")] + pub r#type: u32, + /// The value of the TLV. Must be at least one byte long. + #[prost(bytes = "vec", tag = "2")] + pub value: ::prost::alloc::vec::Vec, +} +impl ::prost::Name for TlvEntry { + const NAME: &'static str = "TlvEntry"; + const PACKAGE: &'static str = "envoy.config.core.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.config.core.v3.TlvEntry".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.config.core.v3.TlvEntry".into() + } +} #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProxyProtocolConfig { /// The PROXY protocol version to use. See for details @@ -1660,6 +1795,32 @@ pub struct ProxyProtocolConfig { /// V2 header. If there is no setting for this field, no TLVs will be passed through. #[prost(message, optional, tag = "2")] pub pass_through_tlvs: ::core::option::Option, + /// This config allows additional TLVs to be included in the upstream PROXY protocol + /// V2 header. Unlike ``pass_through_tlvs``, which passes TLVs from the downstream request, + /// ``added_tlvs`` provides an extension mechanism for defining new TLVs that are included + /// with the upstream request. These TLVs may not be present in the downstream request and + /// can be defined at either the transport socket level or the host level to provide more + /// granular control over the TLVs that are included in the upstream request. + /// + /// Host-level TLVs are specified in the ``metadata.typed_filter_metadata`` field under the + /// ``envoy.transport_sockets.proxy_protocol`` namespace. + /// + /// .. literalinclude:: /_configs/repo/proxy_protocol.yaml + /// :language: yaml + /// :lines: 49-57 + /// :linenos: + /// :lineno-start: 49 + /// :caption: :download:`proxy_protocol.yaml ` + /// + /// **Precedence behavior**: + /// + /// - When a TLV is defined at both the host level and the transport socket level, the value + /// from the host level configuration takes precedence. This allows users to define default TLVs + /// at the transport socket level and override them at the host level. + /// - Any TLV defined in the ``pass_through_tlvs`` field will be overridden by either the host-level + /// or transport socket-level TLV. + #[prost(message, repeated, tag = "3")] + pub added_tlvs: ::prost::alloc::vec::Vec, } /// Nested message and enum types in `ProxyProtocolConfig`. pub mod proxy_protocol_config { @@ -1712,6 +1873,22 @@ impl ::prost::Name for ProxyProtocolConfig { "type.googleapis.com/envoy.config.core.v3.ProxyProtocolConfig".into() } } +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PerHostConfig { + /// Enables per-host configuration for Proxy Protocol. + #[prost(message, repeated, tag = "1")] + pub added_tlvs: ::prost::alloc::vec::Vec, +} +impl ::prost::Name for PerHostConfig { + const NAME: &'static str = "PerHostConfig"; + const PACKAGE: &'static str = "envoy.config.core.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.config.core.v3.PerHostConfig".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.config.core.v3.PerHostConfig".into() + } +} /// gRPC service configuration. This is used by :ref:`ApiConfigSource /// ` and filter configurations. /// \[#next-free-field: 7\] @@ -1739,6 +1916,7 @@ pub struct GrpcService { } /// Nested message and enum types in `GrpcService`. pub mod grpc_service { + /// \[#next-free-field: 6\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct EnvoyGrpc { /// The name of the upstream gRPC cluster. SSL credentials will be supplied @@ -1764,6 +1942,12 @@ pub mod grpc_service { pub max_receive_message_length: ::core::option::Option< super::super::super::super::super::google::protobuf::UInt32Value, >, + /// This provides gRPC client level control over envoy generated headers. + /// If false, the header will be sent but it can be overridden by per stream option. + /// If true, the header will be removed and can not be overridden by per stream option. + /// Default to false. + #[prost(bool, tag = "5")] + pub skip_envoy_headers: bool, } impl ::prost::Name for EnvoyGrpc { const NAME: &'static str = "EnvoyGrpc"; @@ -2743,13 +2927,13 @@ pub struct HealthCheck { pub healthy_edge_interval: ::core::option::Option< super::super::super::super::google::protobuf::Duration, >, - /// .. attention:: - /// This field is deprecated in favor of the extension - /// :ref:`event_logger ` and - /// :ref:`event_log_path ` - /// in the file sink extension. - /// /// Specifies the path to the :ref:`health check event log `. + /// + /// .. attention:: + /// This field is deprecated in favor of the extension + /// :ref:`event_logger ` and + /// :ref:`event_log_path ` + /// in the file sink extension. #[deprecated] #[prost(string, tag = "17")] pub event_log_path: ::prost::alloc::string::String, @@ -3189,7 +3373,7 @@ pub struct QuicKeepAliveSettings { /// /// The value should be smaller than :ref:`connection idle_timeout ` to prevent idle timeout and smaller than max_interval to take effect. /// - /// If absent or zero, disable keepalive probing for a server connection. For a client connection, if :ref:`max_interval ` is also zero, do not keepalive, otherwise use max_interval or QUICHE default to probe all the time. + /// If absent, disable keepalive probing for a server connection. For a client connection, if :ref:`max_interval ` is zero, do not keepalive, otherwise use max_interval or QUICHE default to probe all the time. #[prost(message, optional, tag = "2")] pub initial_interval: ::core::option::Option< super::super::super::super::google::protobuf::Duration, @@ -3206,7 +3390,7 @@ impl ::prost::Name for QuicKeepAliveSettings { } } /// QUIC protocol options which apply to both downstream and upstream connections. -/// \[#next-free-field: 9\] +/// \[#next-free-field: 10\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct QuicProtocolOptions { /// Maximum number of streams that the client can negotiate per connection. 100 @@ -3219,8 +3403,11 @@ pub struct QuicProtocolOptions { /// <`_> size. Valid values range from /// 1 to 16777216 (2^24, maximum supported by QUICHE) and defaults to 16777216 (16 * 1024 * 1024). /// - /// NOTE: 16384 (2^14) is the minimum window size supported in Google QUIC. If configured smaller than it, we will use 16384 instead. - /// QUICHE IETF Quic implementation supports 1 bytes window. We only support increasing the default window size now, so it's also the minimum. + /// .. note:: + /// + /// 16384 (2^14) is the minimum window size supported in Google QUIC. If configured smaller than it, we will use + /// 16384 instead. QUICHE IETF Quic implementation supports 1 bytes window. We only support increasing the default + /// window size now, so it's also the minimum. /// /// This field also acts as a soft limit on the number of bytes Envoy will buffer per-stream in the /// QUIC stream send and receive buffers. Once the buffer reaches this pointer, watermark callbacks will fire to @@ -3233,8 +3420,11 @@ pub struct QuicProtocolOptions { /// flow-control. Valid values rage from 1 to 25165824 (24MB, maximum supported by QUICHE) and defaults /// to 25165824 (24 * 1024 * 1024). /// - /// NOTE: 16384 (2^14) is the minimum window size supported in Google QUIC. We only support increasing the default - /// window size now, so it's also the minimum. + /// .. note:: + /// + /// 16384 (2^14) is the minimum window size supported in Google QUIC. We only support increasing the default + /// window size now, so it's also the minimum. + /// #[prost(message, optional, tag = "3")] pub initial_connection_window_size: ::core::option::Option< super::super::super::super::google::protobuf::UInt32Value, @@ -3267,6 +3457,12 @@ pub struct QuicProtocolOptions { pub idle_network_timeout: ::core::option::Option< super::super::super::super::google::protobuf::Duration, >, + /// Maximum packet length for QUIC connections. It refers to the largest size of a QUIC packet that can be transmitted over the connection. + /// If not specified, one of the `default values in QUICHE <`_> is used. + #[prost(message, optional, tag = "9")] + pub max_packet_length: ::core::option::Option< + super::super::super::super::google::protobuf::UInt64Value, + >, } impl ::prost::Name for QuicProtocolOptions { const NAME: &'static str = "QuicProtocolOptions"; @@ -3285,6 +3481,9 @@ pub struct UpstreamHttpProtocolOptions { /// header when :ref:`override_auto_sni_header ` /// is set, as seen by the :ref:`router filter `. /// Does nothing if a filter before the http router filter sets the corresponding metadata. + /// + /// See :ref:`SNI configuration ` for details on how this + /// interacts with other validation options. #[prost(bool, tag = "1")] pub auto_sni: bool, /// Automatic validate upstream presented certificate for new upstream connections based on the @@ -3292,6 +3491,9 @@ pub struct UpstreamHttpProtocolOptions { /// is set, as seen by the :ref:`router filter `. /// This field is intended to be set with ``auto_sni`` field. /// Does nothing if a filter before the http router filter sets the corresponding metadata. + /// + /// See :ref:`validation configuration ` for how this interacts with + /// other validation options. #[prost(bool, tag = "2")] pub auto_san_validation: bool, /// An optional alternative to the host/authority header to be used for setting the SNI value. @@ -3407,7 +3609,7 @@ impl ::prost::Name for AlternateProtocolsCacheOptions { "type.googleapis.com/envoy.config.core.v3.AlternateProtocolsCacheOptions".into() } } -/// \[#next-free-field: 7\] +/// \[#next-free-field: 8\] #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct HttpProtocolOptions { /// The idle timeout for connections. The idle timeout is defined as the @@ -3431,22 +3633,46 @@ pub struct HttpProtocolOptions { super::super::super::super::google::protobuf::Duration, >, /// The maximum duration of a connection. The duration is defined as a period since a connection - /// was established. If not set, there is no max duration. When max_connection_duration is reached - /// and if there are no active streams, the connection will be closed. If the connection is a - /// downstream connection and there are any active streams, the drain sequence will kick-in, - /// and the connection will be force-closed after the drain period. See :ref:`drain_timeout + /// was established. If not set, there is no max duration. When max_connection_duration is reached, + /// the drain sequence will kick-in. The connection will be closed after the drain timeout period + /// if there are no active streams. See :ref:`drain_timeout /// `. #[prost(message, optional, tag = "3")] pub max_connection_duration: ::core::option::Option< super::super::super::super::google::protobuf::Duration, >, - /// The maximum number of headers. If unconfigured, the default - /// maximum number of request headers allowed is 100. Requests that exceed this limit will receive - /// a 431 response for HTTP/1.x and cause a stream reset for HTTP/2. + /// The maximum number of headers (request headers if configured on HttpConnectionManager, + /// response headers when configured on a cluster). + /// If unconfigured, the default maximum number of headers allowed is 100. + /// The default value for requests can be overridden by setting runtime key ``envoy.reloadable_features.max_request_headers_count``. + /// The default value for responses can be overridden by setting runtime key ``envoy.reloadable_features.max_response_headers_count``. + /// Downstream requests that exceed this limit will receive a 431 response for HTTP/1.x and cause a stream + /// reset for HTTP/2. + /// Upstream responses that exceed this limit will result in a 502 response. #[prost(message, optional, tag = "2")] pub max_headers_count: ::core::option::Option< super::super::super::super::google::protobuf::UInt32Value, >, + /// The maximum size of response headers. + /// If unconfigured, the default is 60 KiB, except for HTTP/1 response headers which have a default + /// of 80KiB. + /// The default value can be overridden by setting runtime key ``envoy.reloadable_features.max_response_headers_size_kb``. + /// Responses that exceed this limit will result in a 503 response. + /// In Envoy, this setting is only valid when configured on an upstream cluster, not on the + /// :ref:`HTTP Connection Manager + /// `. + /// + /// .. note:: + /// + /// Currently some protocol codecs impose limits on the maximum size of a single header. + /// + /// * HTTP/2 (when using nghttp2) limits a single header to around 100kb. + /// * HTTP/3 limits a single header to around 1024kb. + /// + #[prost(message, optional, tag = "7")] + pub max_response_headers_kb: ::core::option::Option< + super::super::super::super::google::protobuf::UInt32Value, + >, /// Total duration to keep alive an HTTP request/response stream. If the time limit is reached the stream will be /// reset independent of any other timeouts. If not specified, this value is not set. #[prost(message, optional, tag = "4")] @@ -3455,9 +3681,15 @@ pub struct HttpProtocolOptions { >, /// Action to take when a client request with a header name containing underscore characters is received. /// If this setting is not specified, the value defaults to ALLOW. - /// Note: upstream responses are not affected by this setting. - /// Note: this only affects client headers. It does not affect headers added - /// by Envoy filters and does not have any impact if added to cluster config. + /// + /// .. note:: + /// + /// Upstream responses are not affected by this setting. + /// + /// .. note:: + /// + /// This only affects client headers. It does not affect headers added by Envoy filters and does not have any + /// impact if added to cluster config. #[prost( enumeration = "http_protocol_options::HeadersWithUnderscoresAction", tag = "5" @@ -3536,7 +3768,7 @@ impl ::prost::Name for HttpProtocolOptions { "type.googleapis.com/envoy.config.core.v3.HttpProtocolOptions".into() } } -/// \[#next-free-field: 11\] +/// \[#next-free-field: 12\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Http1ProtocolOptions { /// Handle HTTP requests with absolute URLs in the requests. These requests @@ -3627,6 +3859,16 @@ pub struct Http1ProtocolOptions { /// to reject custom methods. #[prost(bool, tag = "10")] pub allow_custom_methods: bool, + /// Ignore HTTP/1.1 upgrade values matching any of the supplied matchers. + /// + /// .. note:: + /// + /// ``h2c`` upgrades are always removed for backwards compatibility, regardless of the + /// value in this setting. + #[prost(message, repeated, tag = "11")] + pub ignore_http_11_upgrade: ::prost::alloc::vec::Vec< + super::super::super::r#type::matcher::v3::StringMatcher, + >, } /// Nested message and enum types in `Http1ProtocolOptions`. pub mod http1_protocol_options { @@ -3735,7 +3977,7 @@ impl ::prost::Name for KeepaliveSettings { "type.googleapis.com/envoy.config.core.v3.KeepaliveSettings".into() } } -/// \[#next-free-field: 17\] +/// \[#next-free-field: 18\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Http2ProtocolOptions { /// `Maximum table size <`_> @@ -3766,8 +4008,10 @@ pub struct Http2ProtocolOptions { /// (2^16 - 1, HTTP/2 default) to 2147483647 (2^31 - 1, HTTP/2 maximum) and defaults to 268435456 /// (256 * 1024 * 1024). /// - /// NOTE: 65535 is the initial window size from HTTP/2 spec. We only support increasing the default - /// window size now, so it's also the minimum. + /// .. note:: + /// + /// 65535 is the initial window size from HTTP/2 spec. We only support increasing the default window size now, + /// so it's also the minimum. /// /// This field also acts as a soft limit on the number of bytes Envoy will buffer per-stream in the /// HTTP/2 codec buffers. Once the buffer reaches this pointer, watermark callbacks will fire to @@ -3921,6 +4165,11 @@ pub struct Http2ProtocolOptions { pub use_oghttp2_codec: ::core::option::Option< super::super::super::super::google::protobuf::BoolValue, >, + /// Configure the maximum amount of metadata than can be handled per stream. Defaults to 1 MB. + #[prost(message, optional, tag = "17")] + pub max_metadata_size: ::core::option::Option< + super::super::super::super::google::protobuf::UInt64Value, + >, } /// Nested message and enum types in `Http2ProtocolOptions`. pub mod http2_protocol_options { @@ -3978,7 +4227,7 @@ impl ::prost::Name for GrpcProtocolOptions { } } /// A message which allows using HTTP/3. -/// \[#next-free-field: 7\] +/// \[#next-free-field: 8\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Http3ProtocolOptions { #[prost(message, optional, tag = "1")] @@ -4009,6 +4258,14 @@ pub struct Http3ProtocolOptions { /// information. #[prost(bool, tag = "6")] pub allow_metadata: bool, + /// \[#not-implemented-hide:\] Hiding until Envoy has full HTTP/3 upstream support. + /// Still under implementation. DO NOT USE. + /// + /// Disables QPACK compression related features for HTTP/3 including: + /// No huffman encoding, zero dynamic table capacity and no cookie crumbing. + /// This can be useful for trading off CPU vs bandwidth when an upstream HTTP/3 connection multiplexes multiple downstream connections. + #[prost(bool, tag = "7")] + pub disable_qpack: bool, } impl ::prost::Name for Http3ProtocolOptions { const NAME: &'static str = "Http3ProtocolOptions"; @@ -4126,6 +4383,34 @@ impl ::prost::Name for UdpSocketConfig { "type.googleapis.com/envoy.config.core.v3.UdpSocketConfig".into() } } +/// Configuration for socket cmsg headers. +/// See `:ref:CMSG <`_> for further information. +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct SocketCmsgHeaders { + /// cmsg level. Default is unset. + #[prost(message, optional, tag = "1")] + pub level: ::core::option::Option< + super::super::super::super::google::protobuf::UInt32Value, + >, + /// cmsg type. Default is unset. + #[prost(message, optional, tag = "2")] + pub r#type: ::core::option::Option< + super::super::super::super::google::protobuf::UInt32Value, + >, + /// Expected size of cmsg value. Default is zero. + #[prost(uint32, tag = "3")] + pub expected_size: u32, +} +impl ::prost::Name for SocketCmsgHeaders { + const NAME: &'static str = "SocketCmsgHeaders"; + const PACKAGE: &'static str = "envoy.config.core.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.config.core.v3.SocketCmsgHeaders".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.config.core.v3.SocketCmsgHeaders".into() + } +} /// A list of gRPC methods which can be used as an allowlist, for example. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GrpcMethodList { @@ -4196,6 +4481,11 @@ impl ::prost::Name for HttpService { #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct JsonFormatOptions { /// The output JSON string properties will be sorted. + /// + /// .. note:: + /// As the properties are always sorted, this option has no effect and is deprecated. + /// + #[deprecated] #[prost(bool, tag = "1")] pub sort_properties: bool, } @@ -4219,6 +4509,12 @@ pub struct SubstitutionFormatString { /// * for ``text_format``, the output of the empty operator is changed from ``-`` to an /// empty string, so that empty values are omitted entirely. /// * for ``json_format`` the keys with null values are omitted in the output structure. + /// + /// .. note:: + /// This option does not work perfectly with ``json_format`` as keys with ``null`` values + /// will still be included in the output. See + /// for more details. + /// #[prost(bool, tag = "3")] pub omit_empty_values: bool, /// Specify a ``content_type`` field. diff --git a/src/generated/envoy.config.core.v3.serde.rs b/src/generated/envoy.config.core.v3.serde.rs index 06ab2c8..3b38696 100644 --- a/src/generated/envoy.config.core.v3.serde.rs +++ b/src/generated/envoy.config.core.v3.serde.rs @@ -3269,6 +3269,9 @@ impl serde::Serialize for grpc_service::EnvoyGrpc { if self.max_receive_message_length.is_some() { len += 1; } + if self.skip_envoy_headers { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.config.core.v3.GrpcService.EnvoyGrpc", len)?; if !self.cluster_name.is_empty() { struct_ser.serialize_field("cluster_name", &self.cluster_name)?; @@ -3282,6 +3285,9 @@ impl serde::Serialize for grpc_service::EnvoyGrpc { if let Some(v) = self.max_receive_message_length.as_ref() { struct_ser.serialize_field("max_receive_message_length", v)?; } + if self.skip_envoy_headers { + struct_ser.serialize_field("skip_envoy_headers", &self.skip_envoy_headers)?; + } struct_ser.end() } } @@ -3299,6 +3305,8 @@ impl<'de> serde::Deserialize<'de> for grpc_service::EnvoyGrpc { "retryPolicy", "max_receive_message_length", "maxReceiveMessageLength", + "skip_envoy_headers", + "skipEnvoyHeaders", ]; #[allow(clippy::enum_variant_names)] @@ -3307,6 +3315,7 @@ impl<'de> serde::Deserialize<'de> for grpc_service::EnvoyGrpc { Authority, RetryPolicy, MaxReceiveMessageLength, + SkipEnvoyHeaders, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -3332,6 +3341,7 @@ impl<'de> serde::Deserialize<'de> for grpc_service::EnvoyGrpc { "authority" => Ok(GeneratedField::Authority), "retryPolicy" | "retry_policy" => Ok(GeneratedField::RetryPolicy), "maxReceiveMessageLength" | "max_receive_message_length" => Ok(GeneratedField::MaxReceiveMessageLength), + "skipEnvoyHeaders" | "skip_envoy_headers" => Ok(GeneratedField::SkipEnvoyHeaders), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -3355,6 +3365,7 @@ impl<'de> serde::Deserialize<'de> for grpc_service::EnvoyGrpc { let mut authority__ = None; let mut retry_policy__ = None; let mut max_receive_message_length__ = None; + let mut skip_envoy_headers__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::ClusterName => { @@ -3381,6 +3392,12 @@ impl<'de> serde::Deserialize<'de> for grpc_service::EnvoyGrpc { } max_receive_message_length__ = map_.next_value()?; } + GeneratedField::SkipEnvoyHeaders => { + if skip_envoy_headers__.is_some() { + return Err(serde::de::Error::duplicate_field("skipEnvoyHeaders")); + } + skip_envoy_headers__ = Some(map_.next_value()?); + } } } Ok(grpc_service::EnvoyGrpc { @@ -3388,6 +3405,7 @@ impl<'de> serde::Deserialize<'de> for grpc_service::EnvoyGrpc { authority: authority__.unwrap_or_default(), retry_policy: retry_policy__, max_receive_message_length: max_receive_message_length__, + skip_envoy_headers: skip_envoy_headers__.unwrap_or_default(), }) } } @@ -7014,6 +7032,9 @@ impl serde::Serialize for Http1ProtocolOptions { if self.allow_custom_methods { len += 1; } + if !self.ignore_http_11_upgrade.is_empty() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.config.core.v3.Http1ProtocolOptions", len)?; if let Some(v) = self.allow_absolute_url.as_ref() { struct_ser.serialize_field("allow_absolute_url", v)?; @@ -7045,6 +7066,9 @@ impl serde::Serialize for Http1ProtocolOptions { if self.allow_custom_methods { struct_ser.serialize_field("allow_custom_methods", &self.allow_custom_methods)?; } + if !self.ignore_http_11_upgrade.is_empty() { + struct_ser.serialize_field("ignore_http_11_upgrade", &self.ignore_http_11_upgrade)?; + } struct_ser.end() } } @@ -7075,6 +7099,8 @@ impl<'de> serde::Deserialize<'de> for Http1ProtocolOptions { "useBalsaParser", "allow_custom_methods", "allowCustomMethods", + "ignore_http_11_upgrade", + "ignoreHttp11Upgrade", ]; #[allow(clippy::enum_variant_names)] @@ -7089,6 +7115,7 @@ impl<'de> serde::Deserialize<'de> for Http1ProtocolOptions { SendFullyQualifiedUrl, UseBalsaParser, AllowCustomMethods, + IgnoreHttp11Upgrade, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -7120,6 +7147,7 @@ impl<'de> serde::Deserialize<'de> for Http1ProtocolOptions { "sendFullyQualifiedUrl" | "send_fully_qualified_url" => Ok(GeneratedField::SendFullyQualifiedUrl), "useBalsaParser" | "use_balsa_parser" => Ok(GeneratedField::UseBalsaParser), "allowCustomMethods" | "allow_custom_methods" => Ok(GeneratedField::AllowCustomMethods), + "ignoreHttp11Upgrade" | "ignore_http_11_upgrade" => Ok(GeneratedField::IgnoreHttp11Upgrade), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -7149,6 +7177,7 @@ impl<'de> serde::Deserialize<'de> for Http1ProtocolOptions { let mut send_fully_qualified_url__ = None; let mut use_balsa_parser__ = None; let mut allow_custom_methods__ = None; + let mut ignore_http_11_upgrade__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::AllowAbsoluteUrl => { @@ -7211,6 +7240,12 @@ impl<'de> serde::Deserialize<'de> for Http1ProtocolOptions { } allow_custom_methods__ = Some(map_.next_value()?); } + GeneratedField::IgnoreHttp11Upgrade => { + if ignore_http_11_upgrade__.is_some() { + return Err(serde::de::Error::duplicate_field("ignoreHttp11Upgrade")); + } + ignore_http_11_upgrade__ = Some(map_.next_value()?); + } } } Ok(Http1ProtocolOptions { @@ -7224,6 +7259,7 @@ impl<'de> serde::Deserialize<'de> for Http1ProtocolOptions { send_fully_qualified_url: send_fully_qualified_url__.unwrap_or_default(), use_balsa_parser: use_balsa_parser__, allow_custom_methods: allow_custom_methods__.unwrap_or_default(), + ignore_http_11_upgrade: ignore_http_11_upgrade__.unwrap_or_default(), }) } } @@ -7468,6 +7504,9 @@ impl serde::Serialize for Http2ProtocolOptions { if self.use_oghttp2_codec.is_some() { len += 1; } + if self.max_metadata_size.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.config.core.v3.Http2ProtocolOptions", len)?; if let Some(v) = self.hpack_table_size.as_ref() { struct_ser.serialize_field("hpack_table_size", v)?; @@ -7517,6 +7556,9 @@ impl serde::Serialize for Http2ProtocolOptions { if let Some(v) = self.use_oghttp2_codec.as_ref() { struct_ser.serialize_field("use_oghttp2_codec", v)?; } + if let Some(v) = self.max_metadata_size.as_ref() { + struct_ser.serialize_field("max_metadata_size", v)?; + } struct_ser.end() } } @@ -7559,6 +7601,8 @@ impl<'de> serde::Deserialize<'de> for Http2ProtocolOptions { "connectionKeepalive", "use_oghttp2_codec", "useOghttp2Codec", + "max_metadata_size", + "maxMetadataSize", ]; #[allow(clippy::enum_variant_names)] @@ -7579,6 +7623,7 @@ impl<'de> serde::Deserialize<'de> for Http2ProtocolOptions { CustomSettingsParameters, ConnectionKeepalive, UseOghttp2Codec, + MaxMetadataSize, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -7616,6 +7661,7 @@ impl<'de> serde::Deserialize<'de> for Http2ProtocolOptions { "customSettingsParameters" | "custom_settings_parameters" => Ok(GeneratedField::CustomSettingsParameters), "connectionKeepalive" | "connection_keepalive" => Ok(GeneratedField::ConnectionKeepalive), "useOghttp2Codec" | "use_oghttp2_codec" => Ok(GeneratedField::UseOghttp2Codec), + "maxMetadataSize" | "max_metadata_size" => Ok(GeneratedField::MaxMetadataSize), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -7651,6 +7697,7 @@ impl<'de> serde::Deserialize<'de> for Http2ProtocolOptions { let mut custom_settings_parameters__ = None; let mut connection_keepalive__ = None; let mut use_oghttp2_codec__ = None; + let mut max_metadata_size__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::HpackTableSize => { @@ -7749,6 +7796,12 @@ impl<'de> serde::Deserialize<'de> for Http2ProtocolOptions { } use_oghttp2_codec__ = map_.next_value()?; } + GeneratedField::MaxMetadataSize => { + if max_metadata_size__.is_some() { + return Err(serde::de::Error::duplicate_field("maxMetadataSize")); + } + max_metadata_size__ = map_.next_value()?; + } } } Ok(Http2ProtocolOptions { @@ -7768,6 +7821,7 @@ impl<'de> serde::Deserialize<'de> for Http2ProtocolOptions { custom_settings_parameters: custom_settings_parameters__.unwrap_or_default(), connection_keepalive: connection_keepalive__, use_oghttp2_codec: use_oghttp2_codec__, + max_metadata_size: max_metadata_size__, }) } } @@ -7902,6 +7956,9 @@ impl serde::Serialize for Http3ProtocolOptions { if self.allow_metadata { len += 1; } + if self.disable_qpack { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.config.core.v3.Http3ProtocolOptions", len)?; if let Some(v) = self.quic_protocol_options.as_ref() { struct_ser.serialize_field("quic_protocol_options", v)?; @@ -7915,6 +7972,9 @@ impl serde::Serialize for Http3ProtocolOptions { if self.allow_metadata { struct_ser.serialize_field("allow_metadata", &self.allow_metadata)?; } + if self.disable_qpack { + struct_ser.serialize_field("disable_qpack", &self.disable_qpack)?; + } struct_ser.end() } } @@ -7933,6 +7993,8 @@ impl<'de> serde::Deserialize<'de> for Http3ProtocolOptions { "allowExtendedConnect", "allow_metadata", "allowMetadata", + "disable_qpack", + "disableQpack", ]; #[allow(clippy::enum_variant_names)] @@ -7941,6 +8003,7 @@ impl<'de> serde::Deserialize<'de> for Http3ProtocolOptions { OverrideStreamErrorOnInvalidHttpMessage, AllowExtendedConnect, AllowMetadata, + DisableQpack, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -7966,6 +8029,7 @@ impl<'de> serde::Deserialize<'de> for Http3ProtocolOptions { "overrideStreamErrorOnInvalidHttpMessage" | "override_stream_error_on_invalid_http_message" => Ok(GeneratedField::OverrideStreamErrorOnInvalidHttpMessage), "allowExtendedConnect" | "allow_extended_connect" => Ok(GeneratedField::AllowExtendedConnect), "allowMetadata" | "allow_metadata" => Ok(GeneratedField::AllowMetadata), + "disableQpack" | "disable_qpack" => Ok(GeneratedField::DisableQpack), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -7989,6 +8053,7 @@ impl<'de> serde::Deserialize<'de> for Http3ProtocolOptions { let mut override_stream_error_on_invalid_http_message__ = None; let mut allow_extended_connect__ = None; let mut allow_metadata__ = None; + let mut disable_qpack__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::QuicProtocolOptions => { @@ -8015,6 +8080,12 @@ impl<'de> serde::Deserialize<'de> for Http3ProtocolOptions { } allow_metadata__ = Some(map_.next_value()?); } + GeneratedField::DisableQpack => { + if disable_qpack__.is_some() { + return Err(serde::de::Error::duplicate_field("disableQpack")); + } + disable_qpack__ = Some(map_.next_value()?); + } } } Ok(Http3ProtocolOptions { @@ -8022,6 +8093,7 @@ impl<'de> serde::Deserialize<'de> for Http3ProtocolOptions { override_stream_error_on_invalid_http_message: override_stream_error_on_invalid_http_message__, allow_extended_connect: allow_extended_connect__.unwrap_or_default(), allow_metadata: allow_metadata__.unwrap_or_default(), + disable_qpack: disable_qpack__.unwrap_or_default(), }) } } @@ -8045,6 +8117,9 @@ impl serde::Serialize for HttpProtocolOptions { if self.max_headers_count.is_some() { len += 1; } + if self.max_response_headers_kb.is_some() { + len += 1; + } if self.max_stream_duration.is_some() { len += 1; } @@ -8064,6 +8139,9 @@ impl serde::Serialize for HttpProtocolOptions { if let Some(v) = self.max_headers_count.as_ref() { struct_ser.serialize_field("max_headers_count", v)?; } + if let Some(v) = self.max_response_headers_kb.as_ref() { + struct_ser.serialize_field("max_response_headers_kb", v)?; + } if let Some(v) = self.max_stream_duration.as_ref() { struct_ser.serialize_field("max_stream_duration", v)?; } @@ -8091,6 +8169,8 @@ impl<'de> serde::Deserialize<'de> for HttpProtocolOptions { "maxConnectionDuration", "max_headers_count", "maxHeadersCount", + "max_response_headers_kb", + "maxResponseHeadersKb", "max_stream_duration", "maxStreamDuration", "headers_with_underscores_action", @@ -8104,6 +8184,7 @@ impl<'de> serde::Deserialize<'de> for HttpProtocolOptions { IdleTimeout, MaxConnectionDuration, MaxHeadersCount, + MaxResponseHeadersKb, MaxStreamDuration, HeadersWithUnderscoresAction, MaxRequestsPerConnection, @@ -8131,6 +8212,7 @@ impl<'de> serde::Deserialize<'de> for HttpProtocolOptions { "idleTimeout" | "idle_timeout" => Ok(GeneratedField::IdleTimeout), "maxConnectionDuration" | "max_connection_duration" => Ok(GeneratedField::MaxConnectionDuration), "maxHeadersCount" | "max_headers_count" => Ok(GeneratedField::MaxHeadersCount), + "maxResponseHeadersKb" | "max_response_headers_kb" => Ok(GeneratedField::MaxResponseHeadersKb), "maxStreamDuration" | "max_stream_duration" => Ok(GeneratedField::MaxStreamDuration), "headersWithUnderscoresAction" | "headers_with_underscores_action" => Ok(GeneratedField::HeadersWithUnderscoresAction), "maxRequestsPerConnection" | "max_requests_per_connection" => Ok(GeneratedField::MaxRequestsPerConnection), @@ -8156,6 +8238,7 @@ impl<'de> serde::Deserialize<'de> for HttpProtocolOptions { let mut idle_timeout__ = None; let mut max_connection_duration__ = None; let mut max_headers_count__ = None; + let mut max_response_headers_kb__ = None; let mut max_stream_duration__ = None; let mut headers_with_underscores_action__ = None; let mut max_requests_per_connection__ = None; @@ -8179,6 +8262,12 @@ impl<'de> serde::Deserialize<'de> for HttpProtocolOptions { } max_headers_count__ = map_.next_value()?; } + GeneratedField::MaxResponseHeadersKb => { + if max_response_headers_kb__.is_some() { + return Err(serde::de::Error::duplicate_field("maxResponseHeadersKb")); + } + max_response_headers_kb__ = map_.next_value()?; + } GeneratedField::MaxStreamDuration => { if max_stream_duration__.is_some() { return Err(serde::de::Error::duplicate_field("maxStreamDuration")); @@ -8203,6 +8292,7 @@ impl<'de> serde::Deserialize<'de> for HttpProtocolOptions { idle_timeout: idle_timeout__, max_connection_duration: max_connection_duration__, max_headers_count: max_headers_count__, + max_response_headers_kb: max_response_headers_kb__, max_stream_duration: max_stream_duration__, headers_with_underscores_action: headers_with_underscores_action__.unwrap_or_default(), max_requests_per_connection: max_requests_per_connection__, @@ -8881,6 +8971,9 @@ impl serde::Serialize for KeyValueAppend { { use serde::ser::SerializeStruct; let mut len = 0; + if self.record.is_some() { + len += 1; + } if self.entry.is_some() { len += 1; } @@ -8888,6 +8981,9 @@ impl serde::Serialize for KeyValueAppend { len += 1; } let mut struct_ser = serializer.serialize_struct("envoy.config.core.v3.KeyValueAppend", len)?; + if let Some(v) = self.record.as_ref() { + struct_ser.serialize_field("record", v)?; + } if let Some(v) = self.entry.as_ref() { struct_ser.serialize_field("entry", v)?; } @@ -8906,12 +9002,14 @@ impl<'de> serde::Deserialize<'de> for KeyValueAppend { D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ + "record", "entry", "action", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { + Record, Entry, Action, } @@ -8935,6 +9033,7 @@ impl<'de> serde::Deserialize<'de> for KeyValueAppend { E: serde::de::Error, { match value { + "record" => Ok(GeneratedField::Record), "entry" => Ok(GeneratedField::Entry), "action" => Ok(GeneratedField::Action), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), @@ -8956,10 +9055,17 @@ impl<'de> serde::Deserialize<'de> for KeyValueAppend { where V: serde::de::MapAccess<'de>, { + let mut record__ = None; let mut entry__ = None; let mut action__ = None; while let Some(k) = map_.next_key()? { match k { + GeneratedField::Record => { + if record__.is_some() { + return Err(serde::de::Error::duplicate_field("record")); + } + record__ = map_.next_value()?; + } GeneratedField::Entry => { if entry__.is_some() { return Err(serde::de::Error::duplicate_field("entry")); @@ -8975,6 +9081,7 @@ impl<'de> serde::Deserialize<'de> for KeyValueAppend { } } Ok(KeyValueAppend { + record: record__, entry: entry__, action: action__.unwrap_or_default(), }) @@ -9168,6 +9275,114 @@ impl<'de> serde::Deserialize<'de> for KeyValueMutation { deserializer.deserialize_struct("envoy.config.core.v3.KeyValueMutation", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for KeyValuePair { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.key.is_empty() { + len += 1; + } + if self.value.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.config.core.v3.KeyValuePair", len)?; + if !self.key.is_empty() { + struct_ser.serialize_field("key", &self.key)?; + } + if let Some(v) = self.value.as_ref() { + struct_ser.serialize_field("value", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for KeyValuePair { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "key", + "value", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Key, + Value, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "key" => Ok(GeneratedField::Key), + "value" => Ok(GeneratedField::Value), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = KeyValuePair; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.config.core.v3.KeyValuePair") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut key__ = None; + let mut value__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Key => { + if key__.is_some() { + return Err(serde::de::Error::duplicate_field("key")); + } + key__ = Some(map_.next_value()?); + } + GeneratedField::Value => { + if value__.is_some() { + return Err(serde::de::Error::duplicate_field("value")); + } + value__ = map_.next_value()?; + } + } + } + Ok(KeyValuePair { + key: key__.unwrap_or_default(), + value: value__, + }) + } + } + deserializer.deserialize_struct("envoy.config.core.v3.KeyValuePair", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for Locality { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -9786,6 +10001,98 @@ impl<'de> serde::Deserialize<'de> for PathConfigSource { deserializer.deserialize_struct("envoy.config.core.v3.PathConfigSource", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for PerHostConfig { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.added_tlvs.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.config.core.v3.PerHostConfig", len)?; + if !self.added_tlvs.is_empty() { + struct_ser.serialize_field("added_tlvs", &self.added_tlvs)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for PerHostConfig { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "added_tlvs", + "addedTlvs", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + AddedTlvs, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "addedTlvs" | "added_tlvs" => Ok(GeneratedField::AddedTlvs), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = PerHostConfig; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.config.core.v3.PerHostConfig") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut added_tlvs__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::AddedTlvs => { + if added_tlvs__.is_some() { + return Err(serde::de::Error::duplicate_field("addedTlvs")); + } + added_tlvs__ = Some(map_.next_value()?); + } + } + } + Ok(PerHostConfig { + added_tlvs: added_tlvs__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.config.core.v3.PerHostConfig", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for Pipe { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -9910,6 +10217,9 @@ impl serde::Serialize for ProxyProtocolConfig { if self.pass_through_tlvs.is_some() { len += 1; } + if !self.added_tlvs.is_empty() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.config.core.v3.ProxyProtocolConfig", len)?; if self.version != 0 { let v = proxy_protocol_config::Version::try_from(self.version) @@ -9919,6 +10229,9 @@ impl serde::Serialize for ProxyProtocolConfig { if let Some(v) = self.pass_through_tlvs.as_ref() { struct_ser.serialize_field("pass_through_tlvs", v)?; } + if !self.added_tlvs.is_empty() { + struct_ser.serialize_field("added_tlvs", &self.added_tlvs)?; + } struct_ser.end() } } @@ -9932,12 +10245,15 @@ impl<'de> serde::Deserialize<'de> for ProxyProtocolConfig { "version", "pass_through_tlvs", "passThroughTlvs", + "added_tlvs", + "addedTlvs", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { Version, PassThroughTlvs, + AddedTlvs, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -9961,6 +10277,7 @@ impl<'de> serde::Deserialize<'de> for ProxyProtocolConfig { match value { "version" => Ok(GeneratedField::Version), "passThroughTlvs" | "pass_through_tlvs" => Ok(GeneratedField::PassThroughTlvs), + "addedTlvs" | "added_tlvs" => Ok(GeneratedField::AddedTlvs), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -9982,6 +10299,7 @@ impl<'de> serde::Deserialize<'de> for ProxyProtocolConfig { { let mut version__ = None; let mut pass_through_tlvs__ = None; + let mut added_tlvs__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Version => { @@ -9996,11 +10314,18 @@ impl<'de> serde::Deserialize<'de> for ProxyProtocolConfig { } pass_through_tlvs__ = map_.next_value()?; } + GeneratedField::AddedTlvs => { + if added_tlvs__.is_some() { + return Err(serde::de::Error::duplicate_field("addedTlvs")); + } + added_tlvs__ = Some(map_.next_value()?); + } } } Ok(ProxyProtocolConfig { version: version__.unwrap_or_default(), pass_through_tlvs: pass_through_tlvs__, + added_tlvs: added_tlvs__.unwrap_or_default(), }) } } @@ -10514,6 +10839,9 @@ impl serde::Serialize for QuicProtocolOptions { if self.idle_network_timeout.is_some() { len += 1; } + if self.max_packet_length.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.config.core.v3.QuicProtocolOptions", len)?; if let Some(v) = self.max_concurrent_streams.as_ref() { struct_ser.serialize_field("max_concurrent_streams", v)?; @@ -10539,6 +10867,9 @@ impl serde::Serialize for QuicProtocolOptions { if let Some(v) = self.idle_network_timeout.as_ref() { struct_ser.serialize_field("idle_network_timeout", v)?; } + if let Some(v) = self.max_packet_length.as_ref() { + struct_ser.serialize_field("max_packet_length", v)?; + } struct_ser.end() } } @@ -10565,6 +10896,8 @@ impl<'de> serde::Deserialize<'de> for QuicProtocolOptions { "clientConnectionOptions", "idle_network_timeout", "idleNetworkTimeout", + "max_packet_length", + "maxPacketLength", ]; #[allow(clippy::enum_variant_names)] @@ -10577,6 +10910,7 @@ impl<'de> serde::Deserialize<'de> for QuicProtocolOptions { ConnectionOptions, ClientConnectionOptions, IdleNetworkTimeout, + MaxPacketLength, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -10606,6 +10940,7 @@ impl<'de> serde::Deserialize<'de> for QuicProtocolOptions { "connectionOptions" | "connection_options" => Ok(GeneratedField::ConnectionOptions), "clientConnectionOptions" | "client_connection_options" => Ok(GeneratedField::ClientConnectionOptions), "idleNetworkTimeout" | "idle_network_timeout" => Ok(GeneratedField::IdleNetworkTimeout), + "maxPacketLength" | "max_packet_length" => Ok(GeneratedField::MaxPacketLength), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -10633,6 +10968,7 @@ impl<'de> serde::Deserialize<'de> for QuicProtocolOptions { let mut connection_options__ = None; let mut client_connection_options__ = None; let mut idle_network_timeout__ = None; + let mut max_packet_length__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::MaxConcurrentStreams => { @@ -10683,6 +11019,12 @@ impl<'de> serde::Deserialize<'de> for QuicProtocolOptions { } idle_network_timeout__ = map_.next_value()?; } + GeneratedField::MaxPacketLength => { + if max_packet_length__.is_some() { + return Err(serde::de::Error::duplicate_field("maxPacketLength")); + } + max_packet_length__ = map_.next_value()?; + } } } Ok(QuicProtocolOptions { @@ -10694,6 +11036,7 @@ impl<'de> serde::Deserialize<'de> for QuicProtocolOptions { connection_options: connection_options__.unwrap_or_default(), client_connection_options: client_connection_options__.unwrap_or_default(), idle_network_timeout: idle_network_timeout__, + max_packet_length: max_packet_length__, }) } } @@ -12299,6 +12642,9 @@ impl serde::Serialize for SocketAddress { if self.ipv4_compat { len += 1; } + if !self.network_namespace_filepath.is_empty() { + len += 1; + } if self.port_specifier.is_some() { len += 1; } @@ -12317,6 +12663,9 @@ impl serde::Serialize for SocketAddress { if self.ipv4_compat { struct_ser.serialize_field("ipv4_compat", &self.ipv4_compat)?; } + if !self.network_namespace_filepath.is_empty() { + struct_ser.serialize_field("network_namespace_filepath", &self.network_namespace_filepath)?; + } if let Some(v) = self.port_specifier.as_ref() { match v { socket_address::PortSpecifier::PortValue(v) => { @@ -12343,6 +12692,8 @@ impl<'de> serde::Deserialize<'de> for SocketAddress { "resolverName", "ipv4_compat", "ipv4Compat", + "network_namespace_filepath", + "networkNamespaceFilepath", "port_value", "portValue", "named_port", @@ -12355,6 +12706,7 @@ impl<'de> serde::Deserialize<'de> for SocketAddress { Address, ResolverName, Ipv4Compat, + NetworkNamespaceFilepath, PortValue, NamedPort, } @@ -12382,6 +12734,7 @@ impl<'de> serde::Deserialize<'de> for SocketAddress { "address" => Ok(GeneratedField::Address), "resolverName" | "resolver_name" => Ok(GeneratedField::ResolverName), "ipv4Compat" | "ipv4_compat" => Ok(GeneratedField::Ipv4Compat), + "networkNamespaceFilepath" | "network_namespace_filepath" => Ok(GeneratedField::NetworkNamespaceFilepath), "portValue" | "port_value" => Ok(GeneratedField::PortValue), "namedPort" | "named_port" => Ok(GeneratedField::NamedPort), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), @@ -12407,6 +12760,7 @@ impl<'de> serde::Deserialize<'de> for SocketAddress { let mut address__ = None; let mut resolver_name__ = None; let mut ipv4_compat__ = None; + let mut network_namespace_filepath__ = None; let mut port_specifier__ = None; while let Some(k) = map_.next_key()? { match k { @@ -12434,6 +12788,12 @@ impl<'de> serde::Deserialize<'de> for SocketAddress { } ipv4_compat__ = Some(map_.next_value()?); } + GeneratedField::NetworkNamespaceFilepath => { + if network_namespace_filepath__.is_some() { + return Err(serde::de::Error::duplicate_field("networkNamespaceFilepath")); + } + network_namespace_filepath__ = Some(map_.next_value()?); + } GeneratedField::PortValue => { if port_specifier__.is_some() { return Err(serde::de::Error::duplicate_field("portValue")); @@ -12453,6 +12813,7 @@ impl<'de> serde::Deserialize<'de> for SocketAddress { address: address__.unwrap_or_default(), resolver_name: resolver_name__.unwrap_or_default(), ipv4_compat: ipv4_compat__.unwrap_or_default(), + network_namespace_filepath: network_namespace_filepath__.unwrap_or_default(), port_specifier: port_specifier__, }) } @@ -12531,7 +12892,7 @@ impl<'de> serde::Deserialize<'de> for socket_address::Protocol { deserializer.deserialize_any(GeneratedVisitor) } } -impl serde::Serialize for SocketOption { +impl serde::Serialize for SocketCmsgHeaders { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -12539,53 +12900,187 @@ impl serde::Serialize for SocketOption { { use serde::ser::SerializeStruct; let mut len = 0; - if !self.description.is_empty() { - len += 1; - } - if self.level != 0 { - len += 1; - } - if self.name != 0 { + if self.level.is_some() { len += 1; } - if self.state != 0 { + if self.r#type.is_some() { len += 1; } - if self.value.is_some() { + if self.expected_size != 0 { len += 1; } - let mut struct_ser = serializer.serialize_struct("envoy.config.core.v3.SocketOption", len)?; - if !self.description.is_empty() { - struct_ser.serialize_field("description", &self.description)?; - } - if self.level != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("level", ToString::to_string(&self.level).as_str())?; - } - if self.name != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("name", ToString::to_string(&self.name).as_str())?; + let mut struct_ser = serializer.serialize_struct("envoy.config.core.v3.SocketCmsgHeaders", len)?; + if let Some(v) = self.level.as_ref() { + struct_ser.serialize_field("level", v)?; } - if self.state != 0 { - let v = socket_option::SocketState::try_from(self.state) - .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", self.state)))?; - struct_ser.serialize_field("state", &v)?; + if let Some(v) = self.r#type.as_ref() { + struct_ser.serialize_field("type", v)?; } - if let Some(v) = self.value.as_ref() { - match v { - socket_option::Value::IntValue(v) => { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("int_value", ToString::to_string(&v).as_str())?; - } - socket_option::Value::BufValue(v) => { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("buf_value", pbjson::private::base64::encode(&v).as_str())?; - } - } + if self.expected_size != 0 { + struct_ser.serialize_field("expected_size", &self.expected_size)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for SocketCmsgHeaders { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "level", + "type", + "expected_size", + "expectedSize", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Level, + Type, + ExpectedSize, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "level" => Ok(GeneratedField::Level), + "type" => Ok(GeneratedField::Type), + "expectedSize" | "expected_size" => Ok(GeneratedField::ExpectedSize), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = SocketCmsgHeaders; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.config.core.v3.SocketCmsgHeaders") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut level__ = None; + let mut r#type__ = None; + let mut expected_size__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Level => { + if level__.is_some() { + return Err(serde::de::Error::duplicate_field("level")); + } + level__ = map_.next_value()?; + } + GeneratedField::Type => { + if r#type__.is_some() { + return Err(serde::de::Error::duplicate_field("type")); + } + r#type__ = map_.next_value()?; + } + GeneratedField::ExpectedSize => { + if expected_size__.is_some() { + return Err(serde::de::Error::duplicate_field("expectedSize")); + } + expected_size__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + } + } + Ok(SocketCmsgHeaders { + level: level__, + r#type: r#type__, + expected_size: expected_size__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.config.core.v3.SocketCmsgHeaders", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for SocketOption { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.description.is_empty() { + len += 1; + } + if self.level != 0 { + len += 1; + } + if self.name != 0 { + len += 1; + } + if self.state != 0 { + len += 1; + } + if self.r#type.is_some() { + len += 1; + } + if self.value.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.config.core.v3.SocketOption", len)?; + if !self.description.is_empty() { + struct_ser.serialize_field("description", &self.description)?; + } + if self.level != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("level", ToString::to_string(&self.level).as_str())?; + } + if self.name != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("name", ToString::to_string(&self.name).as_str())?; + } + if self.state != 0 { + let v = socket_option::SocketState::try_from(self.state) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", self.state)))?; + struct_ser.serialize_field("state", &v)?; + } + if let Some(v) = self.r#type.as_ref() { + struct_ser.serialize_field("type", v)?; + } + if let Some(v) = self.value.as_ref() { + match v { + socket_option::Value::IntValue(v) => { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("int_value", ToString::to_string(&v).as_str())?; + } + socket_option::Value::BufValue(v) => { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("buf_value", pbjson::private::base64::encode(&v).as_str())?; + } + } } struct_ser.end() } @@ -12601,6 +13096,7 @@ impl<'de> serde::Deserialize<'de> for SocketOption { "level", "name", "state", + "type", "int_value", "intValue", "buf_value", @@ -12613,6 +13109,7 @@ impl<'de> serde::Deserialize<'de> for SocketOption { Level, Name, State, + Type, IntValue, BufValue, } @@ -12640,6 +13137,7 @@ impl<'de> serde::Deserialize<'de> for SocketOption { "level" => Ok(GeneratedField::Level), "name" => Ok(GeneratedField::Name), "state" => Ok(GeneratedField::State), + "type" => Ok(GeneratedField::Type), "intValue" | "int_value" => Ok(GeneratedField::IntValue), "bufValue" | "buf_value" => Ok(GeneratedField::BufValue), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), @@ -12665,6 +13163,7 @@ impl<'de> serde::Deserialize<'de> for SocketOption { let mut level__ = None; let mut name__ = None; let mut state__ = None; + let mut r#type__ = None; let mut value__ = None; while let Some(k) = map_.next_key()? { match k { @@ -12696,6 +13195,12 @@ impl<'de> serde::Deserialize<'de> for SocketOption { } state__ = Some(map_.next_value::()? as i32); } + GeneratedField::Type => { + if r#type__.is_some() { + return Err(serde::de::Error::duplicate_field("type")); + } + r#type__ = map_.next_value()?; + } GeneratedField::IntValue => { if value__.is_some() { return Err(serde::de::Error::duplicate_field("intValue")); @@ -12715,6 +13220,7 @@ impl<'de> serde::Deserialize<'de> for SocketOption { level: level__.unwrap_or_default(), name: name__.unwrap_or_default(), state: state__.unwrap_or_default(), + r#type: r#type__, value: value__, }) } @@ -12796,6 +13302,256 @@ impl<'de> serde::Deserialize<'de> for socket_option::SocketState { deserializer.deserialize_any(GeneratedVisitor) } } +impl serde::Serialize for socket_option::SocketType { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.stream.is_some() { + len += 1; + } + if self.datagram.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.config.core.v3.SocketOption.SocketType", len)?; + if let Some(v) = self.stream.as_ref() { + struct_ser.serialize_field("stream", v)?; + } + if let Some(v) = self.datagram.as_ref() { + struct_ser.serialize_field("datagram", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for socket_option::SocketType { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "stream", + "datagram", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Stream, + Datagram, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "stream" => Ok(GeneratedField::Stream), + "datagram" => Ok(GeneratedField::Datagram), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = socket_option::SocketType; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.config.core.v3.SocketOption.SocketType") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut stream__ = None; + let mut datagram__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Stream => { + if stream__.is_some() { + return Err(serde::de::Error::duplicate_field("stream")); + } + stream__ = map_.next_value()?; + } + GeneratedField::Datagram => { + if datagram__.is_some() { + return Err(serde::de::Error::duplicate_field("datagram")); + } + datagram__ = map_.next_value()?; + } + } + } + Ok(socket_option::SocketType { + stream: stream__, + datagram: datagram__, + }) + } + } + deserializer.deserialize_struct("envoy.config.core.v3.SocketOption.SocketType", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for socket_option::socket_type::Datagram { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let len = 0; + let struct_ser = serializer.serialize_struct("envoy.config.core.v3.SocketOption.SocketType.Datagram", len)?; + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for socket_option::socket_type::Datagram { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + Err(serde::de::Error::unknown_field(value, FIELDS)) + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = socket_option::socket_type::Datagram; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.config.core.v3.SocketOption.SocketType.Datagram") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + while map_.next_key::()?.is_some() { + let _ = map_.next_value::()?; + } + Ok(socket_option::socket_type::Datagram { + }) + } + } + deserializer.deserialize_struct("envoy.config.core.v3.SocketOption.SocketType.Datagram", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for socket_option::socket_type::Stream { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let len = 0; + let struct_ser = serializer.serialize_struct("envoy.config.core.v3.SocketOption.SocketType.Stream", len)?; + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for socket_option::socket_type::Stream { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + Err(serde::de::Error::unknown_field(value, FIELDS)) + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = socket_option::socket_type::Stream; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.config.core.v3.SocketOption.SocketType.Stream") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + while map_.next_key::()?.is_some() { + let _ = map_.next_value::()?; + } + Ok(socket_option::socket_type::Stream { + }) + } + } + deserializer.deserialize_struct("envoy.config.core.v3.SocketOption.SocketType.Stream", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for SocketOptionsOverride { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -13282,6 +14038,120 @@ impl<'de> serde::Deserialize<'de> for TcpProtocolOptions { deserializer.deserialize_struct("envoy.config.core.v3.TcpProtocolOptions", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for TlvEntry { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.r#type != 0 { + len += 1; + } + if !self.value.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.config.core.v3.TlvEntry", len)?; + if self.r#type != 0 { + struct_ser.serialize_field("type", &self.r#type)?; + } + if !self.value.is_empty() { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("value", pbjson::private::base64::encode(&self.value).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for TlvEntry { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "type", + "value", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Type, + Value, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "type" => Ok(GeneratedField::Type), + "value" => Ok(GeneratedField::Value), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = TlvEntry; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.config.core.v3.TlvEntry") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut r#type__ = None; + let mut value__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Type => { + if r#type__.is_some() { + return Err(serde::de::Error::duplicate_field("type")); + } + r#type__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::Value => { + if value__.is_some() { + return Err(serde::de::Error::duplicate_field("value")); + } + value__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + } + } + Ok(TlvEntry { + r#type: r#type__.unwrap_or_default(), + value: value__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.config.core.v3.TlvEntry", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for TrafficDirection { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/src/generated/envoy.config.endpoint.v3.rs b/src/generated/envoy.config.endpoint.v3.rs index 9eb6628..41cfebb 100644 --- a/src/generated/envoy.config.endpoint.v3.rs +++ b/src/generated/envoy.config.endpoint.v3.rs @@ -162,15 +162,38 @@ impl ::prost::Name for LbEndpoint { "type.googleapis.com/envoy.config.endpoint.v3.LbEndpoint".into() } } +/// LbEndpoint list collection. Entries are `LbEndpoint` resources or references. /// \[#not-implemented-hide:\] -/// A configuration for a LEDS collection. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LbEndpointCollection { + #[prost(message, optional, tag = "1")] + pub entries: ::core::option::Option< + super::super::super::super::xds::core::v3::CollectionEntry, + >, +} +impl ::prost::Name for LbEndpointCollection { + const NAME: &'static str = "LbEndpointCollection"; + const PACKAGE: &'static str = "envoy.config.endpoint.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.config.endpoint.v3.LbEndpointCollection".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.config.endpoint.v3.LbEndpointCollection".into() + } +} +/// A configuration for an LEDS collection. #[derive(Clone, PartialEq, ::prost::Message)] pub struct LedsClusterLocalityConfig { /// Configuration for the source of LEDS updates for a Locality. #[prost(message, optional, tag = "1")] pub leds_config: ::core::option::Option, - /// The xDS transport protocol glob collection resource name. - /// The service is only supported in delta xDS (incremental) mode. + /// The name of the LbEndpoint collection resource. + /// + /// If the name ends in ``/*``, it indicates an LbEndpoint glob collection, + /// which is supported only in the xDS incremental protocol variants. + /// Otherwise, it indicates an LbEndpointCollection list collection. + /// + /// Envoy currently supports only glob collections. #[prost(string, tag = "2")] pub leds_collection_name: ::prost::alloc::string::String, } @@ -187,15 +210,18 @@ impl ::prost::Name for LedsClusterLocalityConfig { /// A group of endpoints belonging to a Locality. /// One can have multiple LocalityLbEndpoints for a locality, but only if /// they have different priorities. -/// \[#next-free-field: 9\] +/// \[#next-free-field: 10\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct LocalityLbEndpoints { /// Identifies location of where the upstream hosts run. #[prost(message, optional, tag = "1")] pub locality: ::core::option::Option, + /// Metadata to provide additional information about the locality endpoints in aggregate. + #[prost(message, optional, tag = "9")] + pub metadata: ::core::option::Option, /// The group of endpoints belonging to the locality specified. - /// [#comment:TODO(adisuissa): Once LEDS is implemented this field needs to be - /// deprecated and replaced by ``load_balancer_endpoints``.] + /// This is ignored if :ref:`leds_cluster_locality_config + /// ` is set. #[prost(message, repeated, tag = "2")] pub lb_endpoints: ::prost::alloc::vec::Vec, /// Optional: Per priority/region/zone/sub_zone weight; at least 1. The load @@ -234,7 +260,6 @@ pub struct LocalityLbEndpoints { pub proximity: ::core::option::Option< super::super::super::super::google::protobuf::UInt32Value, >, - /// \[#not-implemented-hide:\] #[prost(oneof = "locality_lb_endpoints::LbConfig", tags = "7, 8")] pub lb_config: ::core::option::Option, } @@ -258,15 +283,16 @@ pub mod locality_lb_endpoints { .into() } } - /// \[#not-implemented-hide:\] #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum LbConfig { - /// The group of endpoints belonging to the locality. - /// [#comment:TODO(adisuissa): Once LEDS is implemented the ``lb_endpoints`` field - /// needs to be deprecated.] + /// \[#not-implemented-hide:\] + /// Not implemented and deprecated. #[prost(message, tag = "7")] LoadBalancerEndpoints(LbEndpointList), /// LEDS Configuration for the current locality. + /// If this is set, the :ref:`lb_endpoints + /// ` + /// field is ignored. #[prost(message, tag = "8")] LedsClusterLocalityConfig(super::LedsClusterLocalityConfig), } @@ -381,8 +407,9 @@ pub mod cluster_load_assignment { /// to determine the health of the priority level, or in other words assume each host has a weight of 1 for /// this calculation. /// - /// Note: this is not currently implemented for - /// :ref:`locality weighted load balancing `. + /// .. note:: + /// This is not currently implemented for + /// :ref:`locality weighted load balancing `. #[prost(bool, tag = "6")] pub weighted_priority_health: bool, } @@ -437,7 +464,7 @@ impl ::prost::Name for ClusterLoadAssignment { /// These are stats Envoy reports to the management server at a frequency defined by /// :ref:`LoadStatsResponse.load_reporting_interval`. /// Stats per upstream region/zone and optionally per subzone. -/// \[#next-free-field: 9\] +/// \[#next-free-field: 15\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct UpstreamLocalityStats { /// Name of zone, region and optionally endpoint group these metrics were @@ -460,7 +487,45 @@ pub struct UpstreamLocalityStats { /// upstream endpoints in the locality. #[prost(uint64, tag = "8")] pub total_issued_requests: u64, - /// Stats for multi-dimensional load balancing. + /// The total number of connections in an established state at the time of the + /// report. This field is aggregated over all the upstream endpoints in the + /// locality. + /// In Envoy, this information may be based on ``upstream_cx_active metric``. + /// \[#not-implemented-hide:\] + #[prost(uint64, tag = "9")] + pub total_active_connections: u64, + /// The total number of connections opened since the last report. + /// This field is aggregated over all the upstream endpoints in the locality. + /// In Envoy, this information may be based on ``upstream_cx_total`` metric + /// compared to itself between start and end of an interval, i.e. + /// ``upstream_cx_total``(now) - ``upstream_cx_total``(now - + /// load_report_interval). + /// \[#not-implemented-hide:\] + #[prost(uint64, tag = "10")] + pub total_new_connections: u64, + /// The total number of connection failures since the last report. + /// This field is aggregated over all the upstream endpoints in the locality. + /// In Envoy, this information may be based on ``upstream_cx_connect_fail`` + /// metric compared to itself between start and end of an interval, i.e. + /// ``upstream_cx_connect_fail``(now) - ``upstream_cx_connect_fail``(now - + /// load_report_interval). + /// \[#not-implemented-hide:\] + #[prost(uint64, tag = "11")] + pub total_fail_connections: u64, + /// CPU utilization stats for multi-dimensional load balancing. + /// This typically comes from endpoint metrics reported via ORCA. + #[prost(message, optional, tag = "12")] + pub cpu_utilization: ::core::option::Option, + /// Memory utilization for multi-dimensional load balancing. + /// This typically comes from endpoint metrics reported via ORCA. + #[prost(message, optional, tag = "13")] + pub mem_utilization: ::core::option::Option, + /// Blended application-defined utilization for multi-dimensional load balancing. + /// This typically comes from endpoint metrics reported via ORCA. + #[prost(message, optional, tag = "14")] + pub application_utilization: ::core::option::Option, + /// Named stats for multi-dimensional load balancing. + /// These typically come from endpoint metrics reported via ORCA. #[prost(message, repeated, tag = "5")] pub load_metric_stats: ::prost::alloc::vec::Vec, /// Endpoint granularity stats information for this locality. This information @@ -558,6 +623,28 @@ impl ::prost::Name for EndpointLoadMetricStats { "type.googleapis.com/envoy.config.endpoint.v3.EndpointLoadMetricStats".into() } } +/// Same as EndpointLoadMetricStats, except without the metric_name field. +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct UnnamedEndpointLoadMetricStats { + /// Number of calls that finished and included this metric. + #[prost(uint64, tag = "1")] + pub num_requests_finished_with_metric: u64, + /// Sum of metric values across all calls that finished with this metric for + /// load_reporting_interval. + #[prost(double, tag = "2")] + pub total_metric_value: f64, +} +impl ::prost::Name for UnnamedEndpointLoadMetricStats { + const NAME: &'static str = "UnnamedEndpointLoadMetricStats"; + const PACKAGE: &'static str = "envoy.config.endpoint.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.config.endpoint.v3.UnnamedEndpointLoadMetricStats".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.config.endpoint.v3.UnnamedEndpointLoadMetricStats" + .into() + } +} /// Per cluster load stats. Envoy reports these stats a management server in a /// :ref:`LoadStatsRequest` /// Next ID: 7 diff --git a/src/generated/envoy.config.endpoint.v3.serde.rs b/src/generated/envoy.config.endpoint.v3.serde.rs index ac6747f..e4d20b1 100644 --- a/src/generated/envoy.config.endpoint.v3.serde.rs +++ b/src/generated/envoy.config.endpoint.v3.serde.rs @@ -1377,6 +1377,97 @@ impl<'de> serde::Deserialize<'de> for LbEndpoint { deserializer.deserialize_struct("envoy.config.endpoint.v3.LbEndpoint", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for LbEndpointCollection { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.entries.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.config.endpoint.v3.LbEndpointCollection", len)?; + if let Some(v) = self.entries.as_ref() { + struct_ser.serialize_field("entries", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for LbEndpointCollection { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "entries", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Entries, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "entries" => Ok(GeneratedField::Entries), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = LbEndpointCollection; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.config.endpoint.v3.LbEndpointCollection") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut entries__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Entries => { + if entries__.is_some() { + return Err(serde::de::Error::duplicate_field("entries")); + } + entries__ = map_.next_value()?; + } + } + } + Ok(LbEndpointCollection { + entries: entries__, + }) + } + } + deserializer.deserialize_struct("envoy.config.endpoint.v3.LbEndpointCollection", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for LedsClusterLocalityConfig { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -1498,6 +1589,9 @@ impl serde::Serialize for LocalityLbEndpoints { if self.locality.is_some() { len += 1; } + if self.metadata.is_some() { + len += 1; + } if !self.lb_endpoints.is_empty() { len += 1; } @@ -1517,6 +1611,9 @@ impl serde::Serialize for LocalityLbEndpoints { if let Some(v) = self.locality.as_ref() { struct_ser.serialize_field("locality", v)?; } + if let Some(v) = self.metadata.as_ref() { + struct_ser.serialize_field("metadata", v)?; + } if !self.lb_endpoints.is_empty() { struct_ser.serialize_field("lb_endpoints", &self.lb_endpoints)?; } @@ -1550,6 +1647,7 @@ impl<'de> serde::Deserialize<'de> for LocalityLbEndpoints { { const FIELDS: &[&str] = &[ "locality", + "metadata", "lb_endpoints", "lbEndpoints", "load_balancing_weight", @@ -1565,6 +1663,7 @@ impl<'de> serde::Deserialize<'de> for LocalityLbEndpoints { #[allow(clippy::enum_variant_names)] enum GeneratedField { Locality, + Metadata, LbEndpoints, LoadBalancingWeight, Priority, @@ -1593,6 +1692,7 @@ impl<'de> serde::Deserialize<'de> for LocalityLbEndpoints { { match value { "locality" => Ok(GeneratedField::Locality), + "metadata" => Ok(GeneratedField::Metadata), "lbEndpoints" | "lb_endpoints" => Ok(GeneratedField::LbEndpoints), "loadBalancingWeight" | "load_balancing_weight" => Ok(GeneratedField::LoadBalancingWeight), "priority" => Ok(GeneratedField::Priority), @@ -1619,6 +1719,7 @@ impl<'de> serde::Deserialize<'de> for LocalityLbEndpoints { V: serde::de::MapAccess<'de>, { let mut locality__ = None; + let mut metadata__ = None; let mut lb_endpoints__ = None; let mut load_balancing_weight__ = None; let mut priority__ = None; @@ -1632,6 +1733,12 @@ impl<'de> serde::Deserialize<'de> for LocalityLbEndpoints { } locality__ = map_.next_value()?; } + GeneratedField::Metadata => { + if metadata__.is_some() { + return Err(serde::de::Error::duplicate_field("metadata")); + } + metadata__ = map_.next_value()?; + } GeneratedField::LbEndpoints => { if lb_endpoints__.is_some() { return Err(serde::de::Error::duplicate_field("lbEndpoints")); @@ -1676,6 +1783,7 @@ impl<'de> serde::Deserialize<'de> for LocalityLbEndpoints { } Ok(LocalityLbEndpoints { locality: locality__, + metadata: metadata__, lb_endpoints: lb_endpoints__.unwrap_or_default(), load_balancing_weight: load_balancing_weight__, priority: priority__.unwrap_or_default(), @@ -1779,6 +1887,122 @@ impl<'de> serde::Deserialize<'de> for locality_lb_endpoints::LbEndpointList { deserializer.deserialize_struct("envoy.config.endpoint.v3.LocalityLbEndpoints.LbEndpointList", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for UnnamedEndpointLoadMetricStats { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.num_requests_finished_with_metric != 0 { + len += 1; + } + if self.total_metric_value != 0. { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.config.endpoint.v3.UnnamedEndpointLoadMetricStats", len)?; + if self.num_requests_finished_with_metric != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("num_requests_finished_with_metric", ToString::to_string(&self.num_requests_finished_with_metric).as_str())?; + } + if self.total_metric_value != 0. { + struct_ser.serialize_field("total_metric_value", &self.total_metric_value)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for UnnamedEndpointLoadMetricStats { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "num_requests_finished_with_metric", + "numRequestsFinishedWithMetric", + "total_metric_value", + "totalMetricValue", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + NumRequestsFinishedWithMetric, + TotalMetricValue, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "numRequestsFinishedWithMetric" | "num_requests_finished_with_metric" => Ok(GeneratedField::NumRequestsFinishedWithMetric), + "totalMetricValue" | "total_metric_value" => Ok(GeneratedField::TotalMetricValue), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = UnnamedEndpointLoadMetricStats; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.config.endpoint.v3.UnnamedEndpointLoadMetricStats") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut num_requests_finished_with_metric__ = None; + let mut total_metric_value__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::NumRequestsFinishedWithMetric => { + if num_requests_finished_with_metric__.is_some() { + return Err(serde::de::Error::duplicate_field("numRequestsFinishedWithMetric")); + } + num_requests_finished_with_metric__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::TotalMetricValue => { + if total_metric_value__.is_some() { + return Err(serde::de::Error::duplicate_field("totalMetricValue")); + } + total_metric_value__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + } + } + Ok(UnnamedEndpointLoadMetricStats { + num_requests_finished_with_metric: num_requests_finished_with_metric__.unwrap_or_default(), + total_metric_value: total_metric_value__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.config.endpoint.v3.UnnamedEndpointLoadMetricStats", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for UpstreamEndpointStats { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -2016,6 +2240,24 @@ impl serde::Serialize for UpstreamLocalityStats { if self.total_issued_requests != 0 { len += 1; } + if self.total_active_connections != 0 { + len += 1; + } + if self.total_new_connections != 0 { + len += 1; + } + if self.total_fail_connections != 0 { + len += 1; + } + if self.cpu_utilization.is_some() { + len += 1; + } + if self.mem_utilization.is_some() { + len += 1; + } + if self.application_utilization.is_some() { + len += 1; + } if !self.load_metric_stats.is_empty() { len += 1; } @@ -2049,6 +2291,30 @@ impl serde::Serialize for UpstreamLocalityStats { #[allow(clippy::needless_borrows_for_generic_args)] struct_ser.serialize_field("total_issued_requests", ToString::to_string(&self.total_issued_requests).as_str())?; } + if self.total_active_connections != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("total_active_connections", ToString::to_string(&self.total_active_connections).as_str())?; + } + if self.total_new_connections != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("total_new_connections", ToString::to_string(&self.total_new_connections).as_str())?; + } + if self.total_fail_connections != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("total_fail_connections", ToString::to_string(&self.total_fail_connections).as_str())?; + } + if let Some(v) = self.cpu_utilization.as_ref() { + struct_ser.serialize_field("cpu_utilization", v)?; + } + if let Some(v) = self.mem_utilization.as_ref() { + struct_ser.serialize_field("mem_utilization", v)?; + } + if let Some(v) = self.application_utilization.as_ref() { + struct_ser.serialize_field("application_utilization", v)?; + } if !self.load_metric_stats.is_empty() { struct_ser.serialize_field("load_metric_stats", &self.load_metric_stats)?; } @@ -2077,6 +2343,18 @@ impl<'de> serde::Deserialize<'de> for UpstreamLocalityStats { "totalErrorRequests", "total_issued_requests", "totalIssuedRequests", + "total_active_connections", + "totalActiveConnections", + "total_new_connections", + "totalNewConnections", + "total_fail_connections", + "totalFailConnections", + "cpu_utilization", + "cpuUtilization", + "mem_utilization", + "memUtilization", + "application_utilization", + "applicationUtilization", "load_metric_stats", "loadMetricStats", "upstream_endpoint_stats", @@ -2091,6 +2369,12 @@ impl<'de> serde::Deserialize<'de> for UpstreamLocalityStats { TotalRequestsInProgress, TotalErrorRequests, TotalIssuedRequests, + TotalActiveConnections, + TotalNewConnections, + TotalFailConnections, + CpuUtilization, + MemUtilization, + ApplicationUtilization, LoadMetricStats, UpstreamEndpointStats, Priority, @@ -2120,6 +2404,12 @@ impl<'de> serde::Deserialize<'de> for UpstreamLocalityStats { "totalRequestsInProgress" | "total_requests_in_progress" => Ok(GeneratedField::TotalRequestsInProgress), "totalErrorRequests" | "total_error_requests" => Ok(GeneratedField::TotalErrorRequests), "totalIssuedRequests" | "total_issued_requests" => Ok(GeneratedField::TotalIssuedRequests), + "totalActiveConnections" | "total_active_connections" => Ok(GeneratedField::TotalActiveConnections), + "totalNewConnections" | "total_new_connections" => Ok(GeneratedField::TotalNewConnections), + "totalFailConnections" | "total_fail_connections" => Ok(GeneratedField::TotalFailConnections), + "cpuUtilization" | "cpu_utilization" => Ok(GeneratedField::CpuUtilization), + "memUtilization" | "mem_utilization" => Ok(GeneratedField::MemUtilization), + "applicationUtilization" | "application_utilization" => Ok(GeneratedField::ApplicationUtilization), "loadMetricStats" | "load_metric_stats" => Ok(GeneratedField::LoadMetricStats), "upstreamEndpointStats" | "upstream_endpoint_stats" => Ok(GeneratedField::UpstreamEndpointStats), "priority" => Ok(GeneratedField::Priority), @@ -2147,6 +2437,12 @@ impl<'de> serde::Deserialize<'de> for UpstreamLocalityStats { let mut total_requests_in_progress__ = None; let mut total_error_requests__ = None; let mut total_issued_requests__ = None; + let mut total_active_connections__ = None; + let mut total_new_connections__ = None; + let mut total_fail_connections__ = None; + let mut cpu_utilization__ = None; + let mut mem_utilization__ = None; + let mut application_utilization__ = None; let mut load_metric_stats__ = None; let mut upstream_endpoint_stats__ = None; let mut priority__ = None; @@ -2190,6 +2486,48 @@ impl<'de> serde::Deserialize<'de> for UpstreamLocalityStats { Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) ; } + GeneratedField::TotalActiveConnections => { + if total_active_connections__.is_some() { + return Err(serde::de::Error::duplicate_field("totalActiveConnections")); + } + total_active_connections__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::TotalNewConnections => { + if total_new_connections__.is_some() { + return Err(serde::de::Error::duplicate_field("totalNewConnections")); + } + total_new_connections__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::TotalFailConnections => { + if total_fail_connections__.is_some() { + return Err(serde::de::Error::duplicate_field("totalFailConnections")); + } + total_fail_connections__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::CpuUtilization => { + if cpu_utilization__.is_some() { + return Err(serde::de::Error::duplicate_field("cpuUtilization")); + } + cpu_utilization__ = map_.next_value()?; + } + GeneratedField::MemUtilization => { + if mem_utilization__.is_some() { + return Err(serde::de::Error::duplicate_field("memUtilization")); + } + mem_utilization__ = map_.next_value()?; + } + GeneratedField::ApplicationUtilization => { + if application_utilization__.is_some() { + return Err(serde::de::Error::duplicate_field("applicationUtilization")); + } + application_utilization__ = map_.next_value()?; + } GeneratedField::LoadMetricStats => { if load_metric_stats__.is_some() { return Err(serde::de::Error::duplicate_field("loadMetricStats")); @@ -2218,6 +2556,12 @@ impl<'de> serde::Deserialize<'de> for UpstreamLocalityStats { total_requests_in_progress: total_requests_in_progress__.unwrap_or_default(), total_error_requests: total_error_requests__.unwrap_or_default(), total_issued_requests: total_issued_requests__.unwrap_or_default(), + total_active_connections: total_active_connections__.unwrap_or_default(), + total_new_connections: total_new_connections__.unwrap_or_default(), + total_fail_connections: total_fail_connections__.unwrap_or_default(), + cpu_utilization: cpu_utilization__, + mem_utilization: mem_utilization__, + application_utilization: application_utilization__, load_metric_stats: load_metric_stats__.unwrap_or_default(), upstream_endpoint_stats: upstream_endpoint_stats__.unwrap_or_default(), priority: priority__.unwrap_or_default(), diff --git a/src/generated/envoy.config.grpc_credential.v3.rs b/src/generated/envoy.config.grpc_credential.v3.rs index 6319282..4af9e3e 100644 --- a/src/generated/envoy.config.grpc_credential.v3.rs +++ b/src/generated/envoy.config.grpc_credential.v3.rs @@ -1,32 +1,5 @@ // This file is @generated by prost-build. #[derive(Clone, PartialEq, ::prost::Message)] -pub struct AwsIamConfig { - /// The `service namespace - /// <`_> - /// of the Grpc endpoint. - /// - /// Example: appmesh - #[prost(string, tag = "1")] - pub service_name: ::prost::alloc::string::String, - /// The `region <`_> hosting the Grpc - /// endpoint. If unspecified, the extension will use the value in the ``AWS_REGION`` environment - /// variable. - /// - /// Example: us-west-2 - #[prost(string, tag = "2")] - pub region: ::prost::alloc::string::String, -} -impl ::prost::Name for AwsIamConfig { - const NAME: &'static str = "AwsIamConfig"; - const PACKAGE: &'static str = "envoy.config.grpc_credential.v3"; - fn full_name() -> ::prost::alloc::string::String { - "envoy.config.grpc_credential.v3.AwsIamConfig".into() - } - fn type_url() -> ::prost::alloc::string::String { - "type.googleapis.com/envoy.config.grpc_credential.v3.AwsIamConfig".into() - } -} -#[derive(Clone, PartialEq, ::prost::Message)] pub struct FileBasedMetadataConfig { /// Location or inline data of secret to use for authentication of the Google gRPC connection /// this secret will be attached to a header of the gRPC connection diff --git a/src/generated/envoy.config.grpc_credential.v3.serde.rs b/src/generated/envoy.config.grpc_credential.v3.serde.rs index 6c5a626..3107d67 100644 --- a/src/generated/envoy.config.grpc_credential.v3.serde.rs +++ b/src/generated/envoy.config.grpc_credential.v3.serde.rs @@ -1,112 +1,3 @@ -impl serde::Serialize for AwsIamConfig { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.service_name.is_empty() { - len += 1; - } - if !self.region.is_empty() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("envoy.config.grpc_credential.v3.AwsIamConfig", len)?; - if !self.service_name.is_empty() { - struct_ser.serialize_field("service_name", &self.service_name)?; - } - if !self.region.is_empty() { - struct_ser.serialize_field("region", &self.region)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for AwsIamConfig { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "service_name", - "serviceName", - "region", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - ServiceName, - Region, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "serviceName" | "service_name" => Ok(GeneratedField::ServiceName), - "region" => Ok(GeneratedField::Region), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = AwsIamConfig; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct envoy.config.grpc_credential.v3.AwsIamConfig") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut service_name__ = None; - let mut region__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::ServiceName => { - if service_name__.is_some() { - return Err(serde::de::Error::duplicate_field("serviceName")); - } - service_name__ = Some(map_.next_value()?); - } - GeneratedField::Region => { - if region__.is_some() { - return Err(serde::de::Error::duplicate_field("region")); - } - region__ = Some(map_.next_value()?); - } - } - } - Ok(AwsIamConfig { - service_name: service_name__.unwrap_or_default(), - region: region__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("envoy.config.grpc_credential.v3.AwsIamConfig", FIELDS, GeneratedVisitor) - } -} impl serde::Serialize for FileBasedMetadataConfig { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/src/generated/envoy.config.listener.v3.rs b/src/generated/envoy.config.listener.v3.rs index a74dad0..a6586d7 100644 --- a/src/generated/envoy.config.listener.v3.rs +++ b/src/generated/envoy.config.listener.v3.rs @@ -316,45 +316,6 @@ pub struct FilterChain { /// requires that filter chains are uniquely named within a listener. #[prost(string, tag = "7")] pub name: ::prost::alloc::string::String, - /// \[#not-implemented-hide:\] The configuration to specify whether the filter chain will be built on-demand. - /// If this field is not empty, the filter chain will be built on-demand. - /// Otherwise, the filter chain will be built normally and block listener warming. - #[prost(message, optional, tag = "8")] - pub on_demand_configuration: ::core::option::Option< - filter_chain::OnDemandConfiguration, - >, -} -/// Nested message and enum types in `FilterChain`. -pub mod filter_chain { - /// The configuration for on-demand filter chain. If this field is not empty in FilterChain message, - /// a filter chain will be built on-demand. - /// On-demand filter chains help speedup the warming up of listeners since the building and initialization of - /// an on-demand filter chain will be postponed to the arrival of new connection requests that require this filter chain. - /// Filter chains that are not often used can be set as on-demand. - #[derive(Clone, Copy, PartialEq, ::prost::Message)] - pub struct OnDemandConfiguration { - /// The timeout to wait for filter chain placeholders to complete rebuilding. - /// 1. If this field is set to 0, timeout is disabled. - /// 2. If not specified, a default timeout of 15s is used. - /// Rebuilding will wait until dependencies are ready, have failed, or this timeout is reached. - /// Upon failure or timeout, all connections related to this filter chain will be closed. - /// Rebuilding will start again on the next new connection. - #[prost(message, optional, tag = "1")] - pub rebuild_timeout: ::core::option::Option< - super::super::super::super::super::google::protobuf::Duration, - >, - } - impl ::prost::Name for OnDemandConfiguration { - const NAME: &'static str = "OnDemandConfiguration"; - const PACKAGE: &'static str = "envoy.config.listener.v3"; - fn full_name() -> ::prost::alloc::string::String { - "envoy.config.listener.v3.FilterChain.OnDemandConfiguration".into() - } - fn type_url() -> ::prost::alloc::string::String { - "type.googleapis.com/envoy.config.listener.v3.FilterChain.OnDemandConfiguration" - .into() - } - } } impl ::prost::Name for FilterChain { const NAME: &'static str = "FilterChain"; @@ -495,7 +456,7 @@ impl ::prost::Name for ListenerFilter { } } /// Configuration specific to the UDP QUIC listener. -/// \[#next-free-field: 12\] +/// \[#next-free-field: 14\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct QuicProtocolOptions { #[prost(message, optional, tag = "1")] @@ -574,6 +535,19 @@ pub struct QuicProtocolOptions { pub connection_debug_visitor_config: ::core::option::Option< super::super::core::v3::TypedExtensionConfig, >, + /// Configure a type of UDP cmsg to pass to listener filters via QuicReceivedPacket. + /// Both level and type must be specified for cmsg to be saved. + /// Cmsg may be truncated or omitted if expected size is not set. + /// If not specified, no cmsg will be saved to QuicReceivedPacket. + #[prost(message, repeated, tag = "12")] + pub save_cmsg_config: ::prost::alloc::vec::Vec< + super::super::core::v3::SocketCmsgHeaders, + >, + /// If true, the listener will reject connection-establishing packets at the + /// QUIC layer by replying with an empty version negotiation packet to the + /// client. + #[prost(bool, tag = "13")] + pub reject_new_connections: bool, } impl ::prost::Name for QuicProtocolOptions { const NAME: &'static str = "QuicProtocolOptions"; @@ -679,7 +653,7 @@ impl ::prost::Name for ListenerCollection { "type.googleapis.com/envoy.config.listener.v3.ListenerCollection".into() } } -/// \[#next-free-field: 36\] +/// \[#next-free-field: 37\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Listener { /// The unique name by which this listener is known. If no name is provided, @@ -712,6 +686,12 @@ pub struct Listener { /// :ref:`FAQ entry `. #[prost(message, repeated, tag = "3")] pub filter_chains: ::prost::alloc::vec::Vec, + /// Discover filter chains configurations by external service. Dynamic discovery of filter chains is allowed + /// while having statically configured filter chains, however, a filter chain name must be unique within a + /// listener. If a discovered filter chain matches a name of an existing filter chain, it is discarded. + /// \[#not-implemented-hide:\] + #[prost(message, optional, tag = "36")] + pub fcds_config: ::core::option::Option, /// :ref:`Matcher API ` resolving the filter chain name from the /// network properties. This matcher is used as a replacement for the filter chain match condition /// :ref:`filter_chain_match @@ -822,10 +802,10 @@ pub struct Listener { super::super::super::super::google::protobuf::BoolValue, >, /// Additional socket options that may not be present in Envoy source code or - /// precompiled binaries. The socket options can be updated for a listener when + /// precompiled binaries. + /// It is not allowed to update the socket options for any existing address if /// :ref:`enable_reuse_port ` - /// is ``true``. Otherwise, if socket options change during a listener update the update will be rejected - /// to make it clear that the options were not updated. + /// is ``false`` to avoid the conflict when creating new sockets for the listener. #[prost(message, repeated, tag = "13")] pub socket_options: ::prost::alloc::vec::Vec, /// Whether the listener should accept TCP Fast Open (TFO) connections. @@ -936,6 +916,11 @@ pub struct Listener { /// accepted in later event loop iterations. /// If no value is provided Envoy will accept all connections pending accept /// from the kernel. + /// + /// .. note:: + /// + /// It is recommended to lower this value for better overload management and reduced per-event cost. + /// Setting it to 1 is a viable option with no noticeable impact on performance. #[prost(message, optional, tag = "34")] pub max_connections_to_accept_per_socket_event: ::core::option::Option< super::super::super::super::google::protobuf::UInt32Value, @@ -1054,6 +1039,33 @@ pub mod listener { .into() } } + /// Configuration for filter chains discovery. + /// \[#not-implemented-hide:\] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct FcdsConfig { + /// Optional name to present to the filter chain discovery service. This may be an arbitrary name with arbitrary + /// length. If a name is not provided, the listener's name is used. Refer to :ref:`filter_chains `. + /// for details on how listener name is determined if unspecified. In addition, this may be a xdstp:// URL. + #[prost(string, tag = "1")] + pub name: ::prost::alloc::string::String, + /// Configuration for the source of FCDS updates for this listener. + /// .. note:: + /// This discovery service only supports ``AGGREGATED_GRPC`` API type. + #[prost(message, optional, tag = "2")] + pub config_source: ::core::option::Option< + super::super::super::core::v3::ConfigSource, + >, + } + impl ::prost::Name for FcdsConfig { + const NAME: &'static str = "FcdsConfig"; + const PACKAGE: &'static str = "envoy.config.listener.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.config.listener.v3.Listener.FcdsConfig".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.config.listener.v3.Listener.FcdsConfig".into() + } + } #[derive( Clone, Copy, diff --git a/src/generated/envoy.config.listener.v3.serde.rs b/src/generated/envoy.config.listener.v3.serde.rs index 4fc2e18..5f2e68d 100644 --- a/src/generated/envoy.config.listener.v3.serde.rs +++ b/src/generated/envoy.config.listener.v3.serde.rs @@ -498,9 +498,6 @@ impl serde::Serialize for FilterChain { if !self.name.is_empty() { len += 1; } - if self.on_demand_configuration.is_some() { - len += 1; - } let mut struct_ser = serializer.serialize_struct("envoy.config.listener.v3.FilterChain", len)?; if let Some(v) = self.filter_chain_match.as_ref() { struct_ser.serialize_field("filter_chain_match", v)?; @@ -523,9 +520,6 @@ impl serde::Serialize for FilterChain { if !self.name.is_empty() { struct_ser.serialize_field("name", &self.name)?; } - if let Some(v) = self.on_demand_configuration.as_ref() { - struct_ser.serialize_field("on_demand_configuration", v)?; - } struct_ser.end() } } @@ -547,8 +541,6 @@ impl<'de> serde::Deserialize<'de> for FilterChain { "transport_socket_connect_timeout", "transportSocketConnectTimeout", "name", - "on_demand_configuration", - "onDemandConfiguration", ]; #[allow(clippy::enum_variant_names)] @@ -560,7 +552,6 @@ impl<'de> serde::Deserialize<'de> for FilterChain { TransportSocket, TransportSocketConnectTimeout, Name, - OnDemandConfiguration, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -589,7 +580,6 @@ impl<'de> serde::Deserialize<'de> for FilterChain { "transportSocket" | "transport_socket" => Ok(GeneratedField::TransportSocket), "transportSocketConnectTimeout" | "transport_socket_connect_timeout" => Ok(GeneratedField::TransportSocketConnectTimeout), "name" => Ok(GeneratedField::Name), - "onDemandConfiguration" | "on_demand_configuration" => Ok(GeneratedField::OnDemandConfiguration), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -616,7 +606,6 @@ impl<'de> serde::Deserialize<'de> for FilterChain { let mut transport_socket__ = None; let mut transport_socket_connect_timeout__ = None; let mut name__ = None; - let mut on_demand_configuration__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::FilterChainMatch => { @@ -661,12 +650,6 @@ impl<'de> serde::Deserialize<'de> for FilterChain { } name__ = Some(map_.next_value()?); } - GeneratedField::OnDemandConfiguration => { - if on_demand_configuration__.is_some() { - return Err(serde::de::Error::duplicate_field("onDemandConfiguration")); - } - on_demand_configuration__ = map_.next_value()?; - } } } Ok(FilterChain { @@ -677,105 +660,12 @@ impl<'de> serde::Deserialize<'de> for FilterChain { transport_socket: transport_socket__, transport_socket_connect_timeout: transport_socket_connect_timeout__, name: name__.unwrap_or_default(), - on_demand_configuration: on_demand_configuration__, }) } } deserializer.deserialize_struct("envoy.config.listener.v3.FilterChain", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for filter_chain::OnDemandConfiguration { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.rebuild_timeout.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("envoy.config.listener.v3.FilterChain.OnDemandConfiguration", len)?; - if let Some(v) = self.rebuild_timeout.as_ref() { - struct_ser.serialize_field("rebuild_timeout", v)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for filter_chain::OnDemandConfiguration { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "rebuild_timeout", - "rebuildTimeout", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - RebuildTimeout, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "rebuildTimeout" | "rebuild_timeout" => Ok(GeneratedField::RebuildTimeout), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = filter_chain::OnDemandConfiguration; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct envoy.config.listener.v3.FilterChain.OnDemandConfiguration") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut rebuild_timeout__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::RebuildTimeout => { - if rebuild_timeout__.is_some() { - return Err(serde::de::Error::duplicate_field("rebuildTimeout")); - } - rebuild_timeout__ = map_.next_value()?; - } - } - } - Ok(filter_chain::OnDemandConfiguration { - rebuild_timeout: rebuild_timeout__, - }) - } - } - deserializer.deserialize_struct("envoy.config.listener.v3.FilterChain.OnDemandConfiguration", FIELDS, GeneratedVisitor) - } -} impl serde::Serialize for FilterChainMatch { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -1150,6 +1040,9 @@ impl serde::Serialize for Listener { if !self.filter_chains.is_empty() { len += 1; } + if self.fcds_config.is_some() { + len += 1; + } if self.filter_chain_matcher.is_some() { len += 1; } @@ -1250,6 +1143,9 @@ impl serde::Serialize for Listener { if !self.filter_chains.is_empty() { struct_ser.serialize_field("filter_chains", &self.filter_chains)?; } + if let Some(v) = self.fcds_config.as_ref() { + struct_ser.serialize_field("fcds_config", v)?; + } if let Some(v) = self.filter_chain_matcher.as_ref() { struct_ser.serialize_field("filter_chain_matcher", v)?; } @@ -1360,6 +1256,8 @@ impl<'de> serde::Deserialize<'de> for Listener { "statPrefix", "filter_chains", "filterChains", + "fcds_config", + "fcdsConfig", "filter_chain_matcher", "filterChainMatcher", "use_original_dst", @@ -1422,6 +1320,7 @@ impl<'de> serde::Deserialize<'de> for Listener { AdditionalAddresses, StatPrefix, FilterChains, + FcdsConfig, FilterChainMatcher, UseOriginalDst, DefaultFilterChain, @@ -1476,6 +1375,7 @@ impl<'de> serde::Deserialize<'de> for Listener { "additionalAddresses" | "additional_addresses" => Ok(GeneratedField::AdditionalAddresses), "statPrefix" | "stat_prefix" => Ok(GeneratedField::StatPrefix), "filterChains" | "filter_chains" => Ok(GeneratedField::FilterChains), + "fcdsConfig" | "fcds_config" => Ok(GeneratedField::FcdsConfig), "filterChainMatcher" | "filter_chain_matcher" => Ok(GeneratedField::FilterChainMatcher), "useOriginalDst" | "use_original_dst" => Ok(GeneratedField::UseOriginalDst), "defaultFilterChain" | "default_filter_chain" => Ok(GeneratedField::DefaultFilterChain), @@ -1528,6 +1428,7 @@ impl<'de> serde::Deserialize<'de> for Listener { let mut additional_addresses__ = None; let mut stat_prefix__ = None; let mut filter_chains__ = None; + let mut fcds_config__ = None; let mut filter_chain_matcher__ = None; let mut use_original_dst__ = None; let mut default_filter_chain__ = None; @@ -1588,6 +1489,12 @@ impl<'de> serde::Deserialize<'de> for Listener { } filter_chains__ = Some(map_.next_value()?); } + GeneratedField::FcdsConfig => { + if fcds_config__.is_some() { + return Err(serde::de::Error::duplicate_field("fcdsConfig")); + } + fcds_config__ = map_.next_value()?; + } GeneratedField::FilterChainMatcher => { if filter_chain_matcher__.is_some() { return Err(serde::de::Error::duplicate_field("filterChainMatcher")); @@ -1765,6 +1672,7 @@ impl<'de> serde::Deserialize<'de> for Listener { additional_addresses: additional_addresses__.unwrap_or_default(), stat_prefix: stat_prefix__.unwrap_or_default(), filter_chains: filter_chains__.unwrap_or_default(), + fcds_config: fcds_config__, filter_chain_matcher: filter_chain_matcher__, use_original_dst: use_original_dst__, default_filter_chain: default_filter_chain__, @@ -2144,6 +2052,115 @@ impl<'de> serde::Deserialize<'de> for listener::DrainType { deserializer.deserialize_any(GeneratedVisitor) } } +impl serde::Serialize for listener::FcdsConfig { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.name.is_empty() { + len += 1; + } + if self.config_source.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.config.listener.v3.Listener.FcdsConfig", len)?; + if !self.name.is_empty() { + struct_ser.serialize_field("name", &self.name)?; + } + if let Some(v) = self.config_source.as_ref() { + struct_ser.serialize_field("config_source", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for listener::FcdsConfig { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "name", + "config_source", + "configSource", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Name, + ConfigSource, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "name" => Ok(GeneratedField::Name), + "configSource" | "config_source" => Ok(GeneratedField::ConfigSource), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = listener::FcdsConfig; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.config.listener.v3.Listener.FcdsConfig") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut name__ = None; + let mut config_source__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Name => { + if name__.is_some() { + return Err(serde::de::Error::duplicate_field("name")); + } + name__ = Some(map_.next_value()?); + } + GeneratedField::ConfigSource => { + if config_source__.is_some() { + return Err(serde::de::Error::duplicate_field("configSource")); + } + config_source__ = map_.next_value()?; + } + } + } + Ok(listener::FcdsConfig { + name: name__.unwrap_or_default(), + config_source: config_source__, + }) + } + } + deserializer.deserialize_struct("envoy.config.listener.v3.Listener.FcdsConfig", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for listener::InternalListenerConfig { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -2807,6 +2824,12 @@ impl serde::Serialize for QuicProtocolOptions { if self.connection_debug_visitor_config.is_some() { len += 1; } + if !self.save_cmsg_config.is_empty() { + len += 1; + } + if self.reject_new_connections { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.config.listener.v3.QuicProtocolOptions", len)?; if let Some(v) = self.quic_protocol_options.as_ref() { struct_ser.serialize_field("quic_protocol_options", v)?; @@ -2841,6 +2864,12 @@ impl serde::Serialize for QuicProtocolOptions { if let Some(v) = self.connection_debug_visitor_config.as_ref() { struct_ser.serialize_field("connection_debug_visitor_config", v)?; } + if !self.save_cmsg_config.is_empty() { + struct_ser.serialize_field("save_cmsg_config", &self.save_cmsg_config)?; + } + if self.reject_new_connections { + struct_ser.serialize_field("reject_new_connections", &self.reject_new_connections)?; + } struct_ser.end() } } @@ -2872,6 +2901,10 @@ impl<'de> serde::Deserialize<'de> for QuicProtocolOptions { "sendDisableActiveMigration", "connection_debug_visitor_config", "connectionDebugVisitorConfig", + "save_cmsg_config", + "saveCmsgConfig", + "reject_new_connections", + "rejectNewConnections", ]; #[allow(clippy::enum_variant_names)] @@ -2887,6 +2920,8 @@ impl<'de> serde::Deserialize<'de> for QuicProtocolOptions { ServerPreferredAddressConfig, SendDisableActiveMigration, ConnectionDebugVisitorConfig, + SaveCmsgConfig, + RejectNewConnections, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -2919,6 +2954,8 @@ impl<'de> serde::Deserialize<'de> for QuicProtocolOptions { "serverPreferredAddressConfig" | "server_preferred_address_config" => Ok(GeneratedField::ServerPreferredAddressConfig), "sendDisableActiveMigration" | "send_disable_active_migration" => Ok(GeneratedField::SendDisableActiveMigration), "connectionDebugVisitorConfig" | "connection_debug_visitor_config" => Ok(GeneratedField::ConnectionDebugVisitorConfig), + "saveCmsgConfig" | "save_cmsg_config" => Ok(GeneratedField::SaveCmsgConfig), + "rejectNewConnections" | "reject_new_connections" => Ok(GeneratedField::RejectNewConnections), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -2949,6 +2986,8 @@ impl<'de> serde::Deserialize<'de> for QuicProtocolOptions { let mut server_preferred_address_config__ = None; let mut send_disable_active_migration__ = None; let mut connection_debug_visitor_config__ = None; + let mut save_cmsg_config__ = None; + let mut reject_new_connections__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::QuicProtocolOptions => { @@ -3017,6 +3056,18 @@ impl<'de> serde::Deserialize<'de> for QuicProtocolOptions { } connection_debug_visitor_config__ = map_.next_value()?; } + GeneratedField::SaveCmsgConfig => { + if save_cmsg_config__.is_some() { + return Err(serde::de::Error::duplicate_field("saveCmsgConfig")); + } + save_cmsg_config__ = Some(map_.next_value()?); + } + GeneratedField::RejectNewConnections => { + if reject_new_connections__.is_some() { + return Err(serde::de::Error::duplicate_field("rejectNewConnections")); + } + reject_new_connections__ = Some(map_.next_value()?); + } } } Ok(QuicProtocolOptions { @@ -3031,6 +3082,8 @@ impl<'de> serde::Deserialize<'de> for QuicProtocolOptions { server_preferred_address_config: server_preferred_address_config__, send_disable_active_migration: send_disable_active_migration__, connection_debug_visitor_config: connection_debug_visitor_config__, + save_cmsg_config: save_cmsg_config__.unwrap_or_default(), + reject_new_connections: reject_new_connections__.unwrap_or_default(), }) } } diff --git a/src/generated/envoy.config.overload.v3.rs b/src/generated/envoy.config.overload.v3.rs index 193472a..70e8655 100644 --- a/src/generated/envoy.config.overload.v3.rs +++ b/src/generated/envoy.config.overload.v3.rs @@ -172,6 +172,11 @@ pub mod scale_timers_overload_action_config { /// This affects the value of /// :ref:`FilterChain.transport_socket_connect_timeout `. TransportSocketConnect = 3, + /// Adjusts the max connection duration timer for downstream HTTP connections. + /// This affects the value of + /// :ref:`HttpConnectionManager.common_http_protocol_options.max_connection_duration + /// `. + HttpDownstreamConnectionMax = 4, } impl TimerType { /// String value of the enum field names used in the ProtoBuf definition. @@ -184,6 +189,7 @@ pub mod scale_timers_overload_action_config { Self::HttpDownstreamConnectionIdle => "HTTP_DOWNSTREAM_CONNECTION_IDLE", Self::HttpDownstreamStreamIdle => "HTTP_DOWNSTREAM_STREAM_IDLE", Self::TransportSocketConnect => "TRANSPORT_SOCKET_CONNECT", + Self::HttpDownstreamConnectionMax => "HTTP_DOWNSTREAM_CONNECTION_MAX", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -195,6 +201,9 @@ pub mod scale_timers_overload_action_config { } "HTTP_DOWNSTREAM_STREAM_IDLE" => Some(Self::HttpDownstreamStreamIdle), "TRANSPORT_SOCKET_CONNECT" => Some(Self::TransportSocketConnect), + "HTTP_DOWNSTREAM_CONNECTION_MAX" => { + Some(Self::HttpDownstreamConnectionMax) + } _ => None, } } diff --git a/src/generated/envoy.config.overload.v3.serde.rs b/src/generated/envoy.config.overload.v3.serde.rs index 6eab194..1cbad7a 100644 --- a/src/generated/envoy.config.overload.v3.serde.rs +++ b/src/generated/envoy.config.overload.v3.serde.rs @@ -836,6 +836,7 @@ impl serde::Serialize for scale_timers_overload_action_config::TimerType { Self::HttpDownstreamConnectionIdle => "HTTP_DOWNSTREAM_CONNECTION_IDLE", Self::HttpDownstreamStreamIdle => "HTTP_DOWNSTREAM_STREAM_IDLE", Self::TransportSocketConnect => "TRANSPORT_SOCKET_CONNECT", + Self::HttpDownstreamConnectionMax => "HTTP_DOWNSTREAM_CONNECTION_MAX", }; serializer.serialize_str(variant) } @@ -851,6 +852,7 @@ impl<'de> serde::Deserialize<'de> for scale_timers_overload_action_config::Timer "HTTP_DOWNSTREAM_CONNECTION_IDLE", "HTTP_DOWNSTREAM_STREAM_IDLE", "TRANSPORT_SOCKET_CONNECT", + "HTTP_DOWNSTREAM_CONNECTION_MAX", ]; struct GeneratedVisitor; @@ -895,6 +897,7 @@ impl<'de> serde::Deserialize<'de> for scale_timers_overload_action_config::Timer "HTTP_DOWNSTREAM_CONNECTION_IDLE" => Ok(scale_timers_overload_action_config::TimerType::HttpDownstreamConnectionIdle), "HTTP_DOWNSTREAM_STREAM_IDLE" => Ok(scale_timers_overload_action_config::TimerType::HttpDownstreamStreamIdle), "TRANSPORT_SOCKET_CONNECT" => Ok(scale_timers_overload_action_config::TimerType::TransportSocketConnect), + "HTTP_DOWNSTREAM_CONNECTION_MAX" => Ok(scale_timers_overload_action_config::TimerType::HttpDownstreamConnectionMax), _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), } } diff --git a/src/generated/envoy.config.rbac.v3.rs b/src/generated/envoy.config.rbac.v3.rs index 9aa7ddd..f1bbace 100644 --- a/src/generated/envoy.config.rbac.v3.rs +++ b/src/generated/envoy.config.rbac.v3.rs @@ -280,13 +280,46 @@ impl ::prost::Name for Policy { "type.googleapis.com/envoy.config.rbac.v3.Policy".into() } } +/// SourcedMetadata enables matching against metadata from different sources in the request processing +/// pipeline. It extends the base MetadataMatcher functionality by allowing specification of where the +/// metadata should be sourced from, rather than only matching against dynamic metadata. +/// +/// The matcher can be configured to look up metadata from: +/// +/// * Dynamic metadata: Runtime metadata added by filters during request processing +/// * Route metadata: Static metadata configured on the route entry +/// +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SourcedMetadata { + /// Metadata matcher configuration that defines what metadata to match against. This includes the filter name, + /// metadata key path, and expected value. + #[prost(message, optional, tag = "1")] + pub metadata_matcher: ::core::option::Option< + super::super::super::r#type::matcher::v3::MetadataMatcher, + >, + /// Specifies which metadata source should be used for matching. If not set, + /// defaults to DYNAMIC (dynamic metadata). Set to ROUTE to match against + /// static metadata configured on the route entry. + #[prost(enumeration = "MetadataSource", tag = "2")] + pub metadata_source: i32, +} +impl ::prost::Name for SourcedMetadata { + const NAME: &'static str = "SourcedMetadata"; + const PACKAGE: &'static str = "envoy.config.rbac.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.config.rbac.v3.SourcedMetadata".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.config.rbac.v3.SourcedMetadata".into() + } +} /// Permission defines an action (or actions) that a principal can take. -/// \[#next-free-field: 14\] +/// \[#next-free-field: 15\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Permission { #[prost( oneof = "permission::Rule", - tags = "1, 2, 3, 4, 10, 5, 6, 11, 7, 8, 9, 12, 13" + tags = "1, 2, 3, 4, 10, 5, 6, 11, 7, 8, 9, 12, 13, 14" )] pub rule: ::core::option::Option, } @@ -320,10 +353,14 @@ pub mod permission { /// When any is set, it matches any action. #[prost(bool, tag = "3")] Any(bool), - /// A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only - /// available for HTTP request. - /// Note: the pseudo-header :path includes the query and fragment string. Use the ``url_path`` - /// field if you want to match the URL path without the query and fragment string. + /// A header (or pseudo-header such as ``:path`` or ``:method``) on the incoming HTTP request. Only available + /// for HTTP request. + /// + /// .. note:: + /// + /// The pseudo-header ``:path`` includes the query and fragment string. Use the ``url_path`` field if you + /// want to match the URL path without the query and fragment string. + /// #[prost(message, tag = "4")] Header(super::super::super::route::v3::HeaderMatcher), /// A URL path on the incoming HTTP request. Only available for HTTP. @@ -338,7 +375,8 @@ pub mod permission { /// A port number range that describes a range of destination ports connecting to. #[prost(message, tag = "11")] DestinationPortRange(super::super::super::super::r#type::v3::Int32Range), - /// Metadata that describes additional information about the action. + /// Metadata that describes additional information about the action. This field is deprecated; please use + /// :ref:`sourced_metadata` instead. #[prost(message, tag = "7")] Metadata(super::super::super::super::r#type::matcher::v3::MetadataMatcher), /// Negates matching the provided permission. For instance, if the value of @@ -346,8 +384,7 @@ pub mod permission { /// the value of ``not_rule`` would not match, this permission would match. #[prost(message, tag = "8")] NotRule(::prost::alloc::boxed::Box), - /// The request server from the client's connection request. This is - /// typically TLS SNI. + /// The request server from the client's connection request. This is typically TLS SNI. /// /// .. attention:: /// @@ -364,8 +401,7 @@ pub mod permission { /// * A :ref:`listener filter ` may /// overwrite a connection's requested server name within Envoy. /// - /// Please refer to :ref:`this FAQ entry ` to learn to - /// setup SNI. + /// Please refer to :ref:`this FAQ entry ` to learn how to setup SNI. #[prost(message, tag = "9")] RequestedServerName( super::super::super::super::r#type::matcher::v3::StringMatcher, @@ -378,6 +414,10 @@ pub mod permission { /// \[#extension-category: envoy.path.match\] #[prost(message, tag = "13")] UriTemplate(super::super::super::core::v3::TypedExtensionConfig), + /// Matches against metadata from either dynamic state or route configuration. Preferred over the + /// ``metadata`` field as it provides more flexibility in metadata source selection. + #[prost(message, tag = "14")] + SourcedMetadata(super::SourcedMetadata), } } impl ::prost::Name for Permission { @@ -392,12 +432,12 @@ impl ::prost::Name for Permission { } /// Principal defines an identity or a group of identities for a downstream /// subject. -/// \[#next-free-field: 13\] +/// \[#next-free-field: 15\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Principal { #[prost( oneof = "principal::Identifier", - tags = "1, 2, 3, 4, 5, 10, 11, 6, 9, 7, 12, 8" + tags = "1, 2, 3, 4, 5, 10, 11, 6, 9, 7, 12, 8, 13, 14" )] pub identifier: ::core::option::Option, } @@ -421,11 +461,19 @@ pub mod principal { } } /// Authentication attributes for a downstream. + /// It is recommended to NOT use this type, but instead use + /// :ref:`MTlsAuthenticated `, + /// configured via :ref:`custom `, + /// which should be used for most use cases due to its improved security. #[derive(Clone, PartialEq, ::prost::Message)] pub struct Authenticated { /// The name of the principal. If set, The URI SAN or DNS SAN in that order /// is used from the certificate, otherwise the subject field is used. If - /// unset, it applies to any user that is authenticated. + /// unset, it applies to any user that is allowed by the downstream TLS configuration. + /// If :ref:`require_client_certificate ` + /// is false or :ref:`trust_chain_verification ` + /// is set to :ref:`ACCEPT_UNTRUSTED `, + /// then no authentication is required. #[prost(message, optional, tag = "2")] pub principal_name: ::core::option::Option< super::super::super::super::r#type::matcher::v3::StringMatcher, @@ -443,18 +491,20 @@ pub mod principal { } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Identifier { - /// A set of identifiers that all must match in order to define the - /// downstream. + /// A set of identifiers that all must match in order to define the downstream. #[prost(message, tag = "1")] AndIds(Set), - /// A set of identifiers at least one must match in order to define the - /// downstream. + /// A set of identifiers at least one must match in order to define the downstream. #[prost(message, tag = "2")] OrIds(Set), /// When any is set, it matches any downstream. #[prost(bool, tag = "3")] Any(bool), /// Authenticated attributes that identify the downstream. + /// It is recommended to NOT use this field, but instead use + /// :ref:`MTlsAuthenticated `, + /// configured via :ref:`custom `, + /// which should be used for most use cases due to its improved security. #[prost(message, tag = "4")] Authenticated(Authenticated), /// A CIDR block that describes the downstream IP. @@ -467,30 +517,40 @@ pub mod principal { #[prost(message, tag = "5")] SourceIp(super::super::super::core::v3::CidrRange), /// A CIDR block that describes the downstream remote/origin address. - /// Note: This is always the physical peer even if the - /// :ref:`remote_ip ` is - /// inferred from for example the x-forwarder-for header, proxy protocol, - /// etc. + /// + /// .. note:: + /// + /// This is always the physical peer even if the + /// :ref:`remote_ip ` is inferred from the + /// x-forwarder-for header, the proxy protocol, etc. + /// #[prost(message, tag = "10")] DirectRemoteIp(super::super::super::core::v3::CidrRange), /// A CIDR block that describes the downstream remote/origin address. - /// Note: This may not be the physical peer and could be different from the - /// :ref:`direct_remote_ip - /// `. E.g, if the - /// remote ip is inferred from for example the x-forwarder-for header, proxy - /// protocol, etc. + /// + /// .. note:: + /// + /// This may not be the physical peer and could be different from the :ref:`direct_remote_ip + /// `. E.g, if the remote ip is inferred from + /// the x-forwarder-for header, the proxy protocol, etc. + /// #[prost(message, tag = "11")] RemoteIp(super::super::super::core::v3::CidrRange), - /// A header (or pseudo-header such as :path or :method) on the incoming HTTP - /// request. Only available for HTTP request. Note: the pseudo-header :path - /// includes the query and fragment string. Use the ``url_path`` field if you - /// want to match the URL path without the query and fragment string. + /// A header (or pseudo-header such as ``:path`` or ``:method``) on the incoming HTTP request. Only available + /// for HTTP request. + /// + /// .. note:: + /// + /// The pseudo-header ``:path`` includes the query and fragment string. Use the ``url_path`` field if you + /// want to match the URL path without the query and fragment string. + /// #[prost(message, tag = "6")] Header(super::super::super::route::v3::HeaderMatcher), /// A URL path on the incoming HTTP request. Only available for HTTP. #[prost(message, tag = "9")] UrlPath(super::super::super::super::r#type::matcher::v3::PathMatcher), - /// Metadata that describes additional information about the principal. + /// Metadata that describes additional information about the principal. This field is deprecated; please use + /// :ref:`sourced_metadata` instead. #[prost(message, tag = "7")] Metadata(super::super::super::super::r#type::matcher::v3::MetadataMatcher), /// Identifies the principal using a filter state object. @@ -501,6 +561,14 @@ pub mod principal { /// value of ``not_id`` would not match, this principal would match. #[prost(message, tag = "8")] NotId(::prost::alloc::boxed::Box), + /// Matches against metadata from either dynamic state or route configuration. Preferred over the + /// ``metadata`` field as it provides more flexibility in metadata source selection. + #[prost(message, tag = "13")] + SourcedMetadata(super::SourcedMetadata), + /// Extension for configuring custom principals for RBAC. + /// \[#extension-category: envoy.rbac.principals\] + #[prost(message, tag = "14")] + Custom(super::super::super::core::v3::TypedExtensionConfig), } } impl ::prost::Name for Principal { @@ -522,7 +590,7 @@ pub struct Action { /// The action to take if the matcher matches. Every action either allows or denies a request, /// and can also carry out action-specific operations. /// - /// Actions: + /// **Actions:** /// /// * ``ALLOW``: If the request gets matched on ALLOW, it is permitted. /// * ``DENY``: If the request gets matched on DENY, it is not permitted. @@ -531,7 +599,7 @@ pub struct Action { /// ``envoy.common`` will be set to the value ``true``. /// * If the request cannot get matched, it will fallback to ``DENY``. /// - /// Log behavior: + /// **Log behavior:** /// /// If the RBAC matcher contains at least one LOG action, the dynamic /// metadata key ``access_log_hint`` will be set based on if the request @@ -550,3 +618,31 @@ impl ::prost::Name for Action { "type.googleapis.com/envoy.config.rbac.v3.Action".into() } } +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum MetadataSource { + /// Query :ref:`dynamic metadata ` + Dynamic = 0, + /// Query :ref:`route metadata ` + Route = 1, +} +impl MetadataSource { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Dynamic => "DYNAMIC", + Self::Route => "ROUTE", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "DYNAMIC" => Some(Self::Dynamic), + "ROUTE" => Some(Self::Route), + _ => None, + } + } +} diff --git a/src/generated/envoy.config.rbac.v3.serde.rs b/src/generated/envoy.config.rbac.v3.serde.rs index 53e5d6a..af358c2 100644 --- a/src/generated/envoy.config.rbac.v3.serde.rs +++ b/src/generated/envoy.config.rbac.v3.serde.rs @@ -108,6 +108,77 @@ impl<'de> serde::Deserialize<'de> for Action { deserializer.deserialize_struct("envoy.config.rbac.v3.Action", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for MetadataSource { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + let variant = match self { + Self::Dynamic => "DYNAMIC", + Self::Route => "ROUTE", + }; + serializer.serialize_str(variant) + } +} +impl<'de> serde::Deserialize<'de> for MetadataSource { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "DYNAMIC", + "ROUTE", + ]; + + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = MetadataSource; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + fn visit_i64(self, v: i64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) + }) + } + + fn visit_u64(self, v: u64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) + }) + } + + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "DYNAMIC" => Ok(MetadataSource::Dynamic), + "ROUTE" => Ok(MetadataSource::Route), + _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), + } + } + } + deserializer.deserialize_any(GeneratedVisitor) + } +} impl serde::Serialize for Permission { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -161,6 +232,9 @@ impl serde::Serialize for Permission { permission::Rule::UriTemplate(v) => { struct_ser.serialize_field("uri_template", v)?; } + permission::Rule::SourcedMetadata(v) => { + struct_ser.serialize_field("sourced_metadata", v)?; + } } } struct_ser.end() @@ -195,6 +269,8 @@ impl<'de> serde::Deserialize<'de> for Permission { "matcher", "uri_template", "uriTemplate", + "sourced_metadata", + "sourcedMetadata", ]; #[allow(clippy::enum_variant_names)] @@ -212,6 +288,7 @@ impl<'de> serde::Deserialize<'de> for Permission { RequestedServerName, Matcher, UriTemplate, + SourcedMetadata, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -246,6 +323,7 @@ impl<'de> serde::Deserialize<'de> for Permission { "requestedServerName" | "requested_server_name" => Ok(GeneratedField::RequestedServerName), "matcher" => Ok(GeneratedField::Matcher), "uriTemplate" | "uri_template" => Ok(GeneratedField::UriTemplate), + "sourcedMetadata" | "sourced_metadata" => Ok(GeneratedField::SourcedMetadata), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -355,6 +433,13 @@ impl<'de> serde::Deserialize<'de> for Permission { return Err(serde::de::Error::duplicate_field("uriTemplate")); } rule__ = map_.next_value::<::std::option::Option<_>>()?.map(permission::Rule::UriTemplate) +; + } + GeneratedField::SourcedMetadata => { + if rule__.is_some() { + return Err(serde::de::Error::duplicate_field("sourcedMetadata")); + } + rule__ = map_.next_value::<::std::option::Option<_>>()?.map(permission::Rule::SourcedMetadata) ; } } @@ -651,6 +736,12 @@ impl serde::Serialize for Principal { principal::Identifier::NotId(v) => { struct_ser.serialize_field("not_id", v)?; } + principal::Identifier::SourcedMetadata(v) => { + struct_ser.serialize_field("sourced_metadata", v)?; + } + principal::Identifier::Custom(v) => { + struct_ser.serialize_field("custom", v)?; + } } } struct_ser.end() @@ -683,6 +774,9 @@ impl<'de> serde::Deserialize<'de> for Principal { "filterState", "not_id", "notId", + "sourced_metadata", + "sourcedMetadata", + "custom", ]; #[allow(clippy::enum_variant_names)] @@ -699,6 +793,8 @@ impl<'de> serde::Deserialize<'de> for Principal { Metadata, FilterState, NotId, + SourcedMetadata, + Custom, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -732,6 +828,8 @@ impl<'de> serde::Deserialize<'de> for Principal { "metadata" => Ok(GeneratedField::Metadata), "filterState" | "filter_state" => Ok(GeneratedField::FilterState), "notId" | "not_id" => Ok(GeneratedField::NotId), + "sourcedMetadata" | "sourced_metadata" => Ok(GeneratedField::SourcedMetadata), + "custom" => Ok(GeneratedField::Custom), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -835,6 +933,20 @@ impl<'de> serde::Deserialize<'de> for Principal { return Err(serde::de::Error::duplicate_field("notId")); } identifier__ = map_.next_value::<::std::option::Option<_>>()?.map(principal::Identifier::NotId) +; + } + GeneratedField::SourcedMetadata => { + if identifier__.is_some() { + return Err(serde::de::Error::duplicate_field("sourcedMetadata")); + } + identifier__ = map_.next_value::<::std::option::Option<_>>()?.map(principal::Identifier::SourcedMetadata) +; + } + GeneratedField::Custom => { + if identifier__.is_some() { + return Err(serde::de::Error::duplicate_field("custom")); + } + identifier__ = map_.next_value::<::std::option::Option<_>>()?.map(principal::Identifier::Custom) ; } } @@ -1533,3 +1645,115 @@ impl<'de> serde::Deserialize<'de> for rbac::audit_logging_options::AuditLoggerCo deserializer.deserialize_struct("envoy.config.rbac.v3.RBAC.AuditLoggingOptions.AuditLoggerConfig", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for SourcedMetadata { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.metadata_matcher.is_some() { + len += 1; + } + if self.metadata_source != 0 { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.config.rbac.v3.SourcedMetadata", len)?; + if let Some(v) = self.metadata_matcher.as_ref() { + struct_ser.serialize_field("metadata_matcher", v)?; + } + if self.metadata_source != 0 { + let v = MetadataSource::try_from(self.metadata_source) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", self.metadata_source)))?; + struct_ser.serialize_field("metadata_source", &v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for SourcedMetadata { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "metadata_matcher", + "metadataMatcher", + "metadata_source", + "metadataSource", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + MetadataMatcher, + MetadataSource, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "metadataMatcher" | "metadata_matcher" => Ok(GeneratedField::MetadataMatcher), + "metadataSource" | "metadata_source" => Ok(GeneratedField::MetadataSource), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = SourcedMetadata; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.config.rbac.v3.SourcedMetadata") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut metadata_matcher__ = None; + let mut metadata_source__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::MetadataMatcher => { + if metadata_matcher__.is_some() { + return Err(serde::de::Error::duplicate_field("metadataMatcher")); + } + metadata_matcher__ = map_.next_value()?; + } + GeneratedField::MetadataSource => { + if metadata_source__.is_some() { + return Err(serde::de::Error::duplicate_field("metadataSource")); + } + metadata_source__ = Some(map_.next_value::()? as i32); + } + } + } + Ok(SourcedMetadata { + metadata_matcher: metadata_matcher__, + metadata_source: metadata_source__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.config.rbac.v3.SourcedMetadata", FIELDS, GeneratedVisitor) + } +} diff --git a/src/generated/envoy.config.route.v3.rs b/src/generated/envoy.config.route.v3.rs index 5755b97..4c4fbf5 100644 --- a/src/generated/envoy.config.route.v3.rs +++ b/src/generated/envoy.config.route.v3.rs @@ -36,7 +36,6 @@ pub struct VirtualHost { /// Only one of this and ``matcher`` can be specified. #[prost(message, repeated, tag = "3")] pub routes: ::prost::alloc::vec::Vec, - /// \[#next-major-version: This should be included in a oneof with routes wrapped in a message.\] /// The match tree to use when resolving route actions for incoming requests. Only one of this and ``routes`` /// can be specified. #[prost(message, optional, tag = "21")] @@ -589,6 +588,8 @@ impl ::prost::Name for WeightedCluster { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ClusterSpecifierPlugin { /// The name of the plugin and its opaque configuration. + /// + /// \[#extension-category: envoy.router.cluster_specifier_plugin\] #[prost(message, optional, tag = "1")] pub extension: ::core::option::Option, /// If is_optional is not set or is set to false and the plugin defined by this message is not a @@ -609,7 +610,7 @@ impl ::prost::Name for ClusterSpecifierPlugin { "type.googleapis.com/envoy.config.route.v3.ClusterSpecifierPlugin".into() } } -/// \[#next-free-field: 16\] +/// \[#next-free-field: 17\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct RouteMatch { /// Indicates that prefix/path matching should be case sensitive. The default @@ -680,6 +681,14 @@ pub struct RouteMatch { pub dynamic_metadata: ::prost::alloc::vec::Vec< super::super::super::r#type::matcher::v3::MetadataMatcher, >, + /// Specifies a set of filter state matchers on which the route should match. + /// The router will check the filter state against all the specified filter state matchers. + /// If the number of specified filter state matchers is nonzero, they all must match the + /// filter state for a match to occur. + #[prost(message, repeated, tag = "16")] + pub filter_state: ::prost::alloc::vec::Vec< + super::super::super::r#type::matcher::v3::FilterStateMatcher, + >, #[prost(oneof = "route_match::PathSpecifier", tags = "1, 2, 10, 12, 14, 15")] pub path_specifier: ::core::option::Option, } @@ -1183,6 +1192,18 @@ pub struct RouteAction { pub max_stream_duration: ::core::option::Option, #[prost(oneof = "route_action::ClusterSpecifier", tags = "1, 2, 3, 37, 39")] pub cluster_specifier: ::core::option::Option, + /// If one of the host rewrite specifiers is set and the + /// :ref:`suppress_envoy_headers + /// ` flag is not + /// set to true, the router filter will place the original host header value before + /// rewriting into the :ref:`x-envoy-original-host + /// ` header. + /// + /// And if the + /// :ref:`append_x_forwarded_host ` + /// is set to true, the original host value will also be appended to the + /// :ref:`config_http_conn_man_headers_x-forwarded-host` header. + /// #[prost(oneof = "route_action::HostRewriteSpecifier", tags = "6, 7, 29, 35")] pub host_rewrite_specifier: ::core::option::Option< route_action::HostRewriteSpecifier, @@ -1243,7 +1264,10 @@ pub mod route_action { pub runtime_fraction: ::core::option::Option< super::super::super::core::v3::RuntimeFractionalPercent, >, - /// Determines if the trace span should be sampled. Defaults to true. + /// Specifies whether the trace span for the shadow request should be sampled. If this field is not explicitly set, + /// the shadow request will inherit the sampling decision of its parent span. This ensures consistency with the trace + /// sampling policy of the original request and prevents oversampling, especially in scenarios where runtime sampling + /// is disabled. #[prost(message, optional, tag = "4")] pub trace_sampled: ::core::option::Option< super::super::super::super::super::google::protobuf::BoolValue, @@ -1699,13 +1723,22 @@ pub mod route_action { #[prost(message, tag = "39")] InlineClusterSpecifierPlugin(super::ClusterSpecifierPlugin), } + /// If one of the host rewrite specifiers is set and the + /// :ref:`suppress_envoy_headers + /// ` flag is not + /// set to true, the router filter will place the original host header value before + /// rewriting into the :ref:`x-envoy-original-host + /// ` header. + /// + /// And if the + /// :ref:`append_x_forwarded_host ` + /// is set to true, the original host value will also be appended to the + /// :ref:`config_http_conn_man_headers_x-forwarded-host` header. + /// #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum HostRewriteSpecifier { /// Indicates that during forwarding, the host header will be swapped with - /// this value. Using this option will append the - /// :ref:`config_http_conn_man_headers_x-forwarded-host` header if - /// :ref:`append_x_forwarded_host ` - /// is set. + /// this value. #[prost(string, tag = "6")] HostRewriteLiteral(::prost::alloc::string::String), /// Indicates that during forwarding, the host header will be swapped with @@ -1714,18 +1747,12 @@ pub mod route_action { /// type ``strict_dns`` or ``logical_dns``, /// or when :ref:`hostname ` /// field is not empty. Setting this to true with other cluster types - /// has no effect. Using this option will append the - /// :ref:`config_http_conn_man_headers_x-forwarded-host` header if - /// :ref:`append_x_forwarded_host ` - /// is set. + /// has no effect. #[prost(message, tag = "7")] AutoHostRewrite(super::super::super::super::super::google::protobuf::BoolValue), /// Indicates that during forwarding, the host header will be swapped with the content of given /// downstream or :ref:`custom ` header. - /// If header value is empty, host header is left intact. Using this option will append the - /// :ref:`config_http_conn_man_headers_x-forwarded-host` header if - /// :ref:`append_x_forwarded_host ` - /// is set. + /// If header value is empty, host header is left intact. /// /// .. attention:: /// @@ -1740,10 +1767,6 @@ pub mod route_action { /// Indicates that during forwarding, the host header will be swapped with /// the result of the regex substitution executed on path value with query and fragment removed. /// This is useful for transitioning variable content between path segment and subdomain. - /// Using this option will append the - /// :ref:`config_http_conn_man_headers_x-forwarded-host` header if - /// :ref:`append_x_forwarded_host ` - /// is set. /// /// For example with the following config: /// @@ -2479,6 +2502,7 @@ impl ::prost::Name for VirtualCluster { } /// Global rate limiting :ref:`architecture overview `. /// Also applies to Local rate limiting :ref:`using descriptors `. +/// \[#next-free-field: 7\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct RateLimit { /// Refers to the stage set in the filter. The rate limit configuration only @@ -2488,11 +2512,21 @@ pub struct RateLimit { /// .. note:: /// /// The filter supports a range of 0 - 10 inclusively for stage numbers. + /// + /// .. note:: + /// This is not supported if the rate limit action is configured in the ``typed_per_filter_config`` like + /// :ref:`VirtualHost.typed_per_filter_config` or + /// :ref:`Route.typed_per_filter_config`, etc. #[prost(message, optional, tag = "1")] pub stage: ::core::option::Option< super::super::super::super::google::protobuf::UInt32Value, >, /// The key to be set in runtime to disable this rate limit configuration. + /// + /// .. note:: + /// This is not supported if the rate limit action is configured in the ``typed_per_filter_config`` like + /// :ref:`VirtualHost.typed_per_filter_config` or + /// :ref:`Route.typed_per_filter_config`, etc. #[prost(string, tag = "2")] pub disable_key: ::prost::alloc::string::String, /// A list of actions that are to be applied for this rate limit configuration. @@ -2507,17 +2541,48 @@ pub struct RateLimit { /// rate limit configuration. If the override value is invalid or cannot be resolved /// from metadata, no override is provided. See :ref:`rate limit override /// ` for more information. + /// + /// .. note:: + /// This is not supported if the rate limit action is configured in the ``typed_per_filter_config`` like + /// :ref:`VirtualHost.typed_per_filter_config` or + /// :ref:`Route.typed_per_filter_config`, etc. #[prost(message, optional, tag = "4")] pub limit: ::core::option::Option, + /// An optional hits addend to be appended to the descriptor produced by this rate limit + /// configuration. + /// + /// .. note:: + /// This is only supported if the rate limit action is configured in the ``typed_per_filter_config`` like + /// :ref:`VirtualHost.typed_per_filter_config` or + /// :ref:`Route.typed_per_filter_config`, etc. + #[prost(message, optional, tag = "5")] + pub hits_addend: ::core::option::Option, + /// If true, the rate limit request will be applied when the stream completes. The default value is false. + /// This is useful when the rate limit budget needs to reflect the response context that is not available + /// on the request path. + /// + /// For example, let's say the upstream service calculates the usage statistics and returns them in the response body + /// and we want to utilize these numbers to apply the rate limit action for the subsequent requests. + /// Combined with another filter that can set the desired addend based on the response (e.g. Lua filter), + /// this can be used to subtract the usage statistics from the rate limit budget. + /// + /// A rate limit applied on the stream completion is "fire-and-forget" by nature, and rate limit is not enforced by this config. + /// In other words, the current request won't be blocked when this is true, but the budget will be updated for the subsequent + /// requests based on the action with this field set to true. Users should ensure that the rate limit is enforced by the actions + /// applied on the request path, i.e. the ones with this field set to false. + /// + /// Currently, this is only supported by the HTTP global rate filter. + #[prost(bool, tag = "6")] + pub apply_on_stream_done: bool, } /// Nested message and enum types in `RateLimit`. pub mod rate_limit { - /// \[#next-free-field: 12\] + /// \[#next-free-field: 13\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Action { #[prost( oneof = "action::ActionSpecifier", - tags = "1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11" + tags = "1, 2, 3, 12, 4, 5, 6, 7, 8, 9, 10, 11" )] pub action_specifier: ::core::option::Option, } @@ -2588,9 +2653,18 @@ pub mod rate_limit { /// The key to use in the descriptor entry. #[prost(string, tag = "2")] pub descriptor_key: ::prost::alloc::string::String, - /// If set to true, Envoy skips the descriptor while calling rate limiting service - /// when header is not present in the request. By default it skips calling the - /// rate limiting service if this header is not present in the request. + /// Controls the behavior when the specified header is not present in the request. + /// + /// If set to ``false`` (default): + /// + /// * Envoy does **NOT** call the rate limiting service for this descriptor. + /// * Useful if the header is optional and you prefer to skip rate limiting when it's absent. + /// + /// If set to ``true``: + /// + /// * Envoy calls the rate limiting service but omits this descriptor if the header is missing. + /// * Useful if you want Envoy to enforce rate limiting even when the header is not present. + /// #[prost(bool, tag = "3")] pub skip_if_absent: bool, } @@ -2605,6 +2679,48 @@ pub mod rate_limit { .into() } } + /// The following descriptor entry is appended when a query parameter contains a key that matches the + /// ``query_parameter_name``: + /// + /// .. code-block:: cpp + /// + /// ("", "") + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct QueryParameters { + /// The name of the query parameter to use for rate limiting. Value of this query parameter is used to populate + /// the value of the descriptor entry for the descriptor_key. + #[prost(string, tag = "1")] + pub query_parameter_name: ::prost::alloc::string::String, + /// The key to use when creating the rate limit descriptor entry. his descriptor key will be used to identify the + /// rate limit rule in the rate limiting service. + #[prost(string, tag = "2")] + pub descriptor_key: ::prost::alloc::string::String, + /// Controls the behavior when the specified query parameter is not present in the request. + /// + /// If set to ``false`` (default): + /// + /// * Envoy does **NOT** call the rate limiting service for this descriptor. + /// * Useful if the query parameter is optional and you prefer to skip rate limiting when it's absent. + /// + /// If set to ``true``: + /// + /// * Envoy calls the rate limiting service but omits this descriptor if the query parameter is missing. + /// * Useful if you want Envoy to enforce rate limiting even when the query parameter is not present. + /// + #[prost(bool, tag = "3")] + pub skip_if_absent: bool, + } + impl ::prost::Name for QueryParameters { + const NAME: &'static str = "QueryParameters"; + const PACKAGE: &'static str = "envoy.config.route.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.config.route.v3.RateLimit.Action.QueryParameters".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.config.route.v3.RateLimit.Action.QueryParameters" + .into() + } + } /// The following descriptor entry is appended to the descriptor and is populated using the /// trusted address from :ref:`x-forwarded-for `: /// @@ -2789,9 +2905,19 @@ pub mod rate_limit { /// Source of metadata #[prost(enumeration = "meta_data::Source", tag = "4")] pub source: i32, - /// If set to true, Envoy skips the descriptor while calling rate limiting service - /// when ``metadata_key`` is empty and ``default_value`` is not set. By default it skips calling the - /// rate limiting service in that case. + /// Controls the behavior when the specified ``metadata_key`` is empty and ``default_value`` is not set. + /// + /// If set to ``false`` (default): + /// + /// * Envoy does **NOT** call the rate limiting service for this descriptor. + /// * Useful if the metadata is optional and you prefer to skip rate limiting when it's absent. + /// + /// If set to ``true``: + /// + /// * Envoy calls the rate limiting service but omits this descriptor if the ``metadata_key`` is empty and + /// ``default_value`` is missing. + /// * Useful if you want Envoy to enforce rate limiting even when the metadata is not present. + /// #[prost(bool, tag = "5")] pub skip_if_absent: bool, } @@ -2900,6 +3026,9 @@ pub mod rate_limit { /// Rate limit on request headers. #[prost(message, tag = "3")] RequestHeaders(RequestHeaders), + /// Rate limit on query parameters. + #[prost(message, tag = "12")] + QueryParameters(QueryParameters), /// Rate limit on remote address. #[prost(message, tag = "4")] RemoteAddress(RemoteAddress), @@ -2993,6 +3122,46 @@ pub mod rate_limit { "type.googleapis.com/envoy.config.route.v3.RateLimit.Override".into() } } + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct HitsAddend { + /// Fixed number of hits to add to the rate limit descriptor. + /// + /// One of the ``number`` or ``format`` fields should be set but not both. + #[prost(message, optional, tag = "1")] + pub number: ::core::option::Option< + super::super::super::super::super::google::protobuf::UInt64Value, + >, + /// Substitution format string to extract the number of hits to add to the rate limit descriptor. + /// The same :ref:`format specifier ` as used for + /// :ref:`HTTP access logging ` applies here. + /// + /// .. note:: + /// + /// The format string must contains only single valid substitution field. If the format string + /// not meets the requirement, the configuration will be rejected. + /// + /// The substitution field should generates a non-negative number or string representation of + /// a non-negative number. The value of the non-negative number should be less than or equal + /// to 1000000000 like the ``number`` field. If the output of the substitution field not meet + /// the requirement, this will be treated as an error and the current descriptor will be ignored. + /// + /// For example, the ``%BYTES_RECEIVED%`` format string will be replaced with the number of bytes + /// received in the request. + /// + /// One of the ``number`` or ``format`` fields should be set but not both. + #[prost(string, tag = "2")] + pub format: ::prost::alloc::string::String, + } + impl ::prost::Name for HitsAddend { + const NAME: &'static str = "HitsAddend"; + const PACKAGE: &'static str = "envoy.config.route.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.config.route.v3.RateLimit.HitsAddend".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.config.route.v3.RateLimit.HitsAddend".into() + } + } } impl ::prost::Name for RateLimit { const NAME: &'static str = "RateLimit"; diff --git a/src/generated/envoy.config.route.v3.serde.rs b/src/generated/envoy.config.route.v3.serde.rs index 7984582..4144c4f 100644 --- a/src/generated/envoy.config.route.v3.serde.rs +++ b/src/generated/envoy.config.route.v3.serde.rs @@ -1556,6 +1556,12 @@ impl serde::Serialize for RateLimit { if self.limit.is_some() { len += 1; } + if self.hits_addend.is_some() { + len += 1; + } + if self.apply_on_stream_done { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.config.route.v3.RateLimit", len)?; if let Some(v) = self.stage.as_ref() { struct_ser.serialize_field("stage", v)?; @@ -1569,6 +1575,12 @@ impl serde::Serialize for RateLimit { if let Some(v) = self.limit.as_ref() { struct_ser.serialize_field("limit", v)?; } + if let Some(v) = self.hits_addend.as_ref() { + struct_ser.serialize_field("hits_addend", v)?; + } + if self.apply_on_stream_done { + struct_ser.serialize_field("apply_on_stream_done", &self.apply_on_stream_done)?; + } struct_ser.end() } } @@ -1584,6 +1596,10 @@ impl<'de> serde::Deserialize<'de> for RateLimit { "disableKey", "actions", "limit", + "hits_addend", + "hitsAddend", + "apply_on_stream_done", + "applyOnStreamDone", ]; #[allow(clippy::enum_variant_names)] @@ -1592,6 +1608,8 @@ impl<'de> serde::Deserialize<'de> for RateLimit { DisableKey, Actions, Limit, + HitsAddend, + ApplyOnStreamDone, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -1617,6 +1635,8 @@ impl<'de> serde::Deserialize<'de> for RateLimit { "disableKey" | "disable_key" => Ok(GeneratedField::DisableKey), "actions" => Ok(GeneratedField::Actions), "limit" => Ok(GeneratedField::Limit), + "hitsAddend" | "hits_addend" => Ok(GeneratedField::HitsAddend), + "applyOnStreamDone" | "apply_on_stream_done" => Ok(GeneratedField::ApplyOnStreamDone), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -1640,6 +1660,8 @@ impl<'de> serde::Deserialize<'de> for RateLimit { let mut disable_key__ = None; let mut actions__ = None; let mut limit__ = None; + let mut hits_addend__ = None; + let mut apply_on_stream_done__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Stage => { @@ -1666,6 +1688,18 @@ impl<'de> serde::Deserialize<'de> for RateLimit { } limit__ = map_.next_value()?; } + GeneratedField::HitsAddend => { + if hits_addend__.is_some() { + return Err(serde::de::Error::duplicate_field("hitsAddend")); + } + hits_addend__ = map_.next_value()?; + } + GeneratedField::ApplyOnStreamDone => { + if apply_on_stream_done__.is_some() { + return Err(serde::de::Error::duplicate_field("applyOnStreamDone")); + } + apply_on_stream_done__ = Some(map_.next_value()?); + } } } Ok(RateLimit { @@ -1673,6 +1707,8 @@ impl<'de> serde::Deserialize<'de> for RateLimit { disable_key: disable_key__.unwrap_or_default(), actions: actions__.unwrap_or_default(), limit: limit__, + hits_addend: hits_addend__, + apply_on_stream_done: apply_on_stream_done__.unwrap_or_default(), }) } } @@ -1702,6 +1738,9 @@ impl serde::Serialize for rate_limit::Action { rate_limit::action::ActionSpecifier::RequestHeaders(v) => { struct_ser.serialize_field("request_headers", v)?; } + rate_limit::action::ActionSpecifier::QueryParameters(v) => { + struct_ser.serialize_field("query_parameters", v)?; + } rate_limit::action::ActionSpecifier::RemoteAddress(v) => { struct_ser.serialize_field("remote_address", v)?; } @@ -1744,6 +1783,8 @@ impl<'de> serde::Deserialize<'de> for rate_limit::Action { "destinationCluster", "request_headers", "requestHeaders", + "query_parameters", + "queryParameters", "remote_address", "remoteAddress", "generic_key", @@ -1765,6 +1806,7 @@ impl<'de> serde::Deserialize<'de> for rate_limit::Action { SourceCluster, DestinationCluster, RequestHeaders, + QueryParameters, RemoteAddress, GenericKey, HeaderValueMatch, @@ -1797,6 +1839,7 @@ impl<'de> serde::Deserialize<'de> for rate_limit::Action { "sourceCluster" | "source_cluster" => Ok(GeneratedField::SourceCluster), "destinationCluster" | "destination_cluster" => Ok(GeneratedField::DestinationCluster), "requestHeaders" | "request_headers" => Ok(GeneratedField::RequestHeaders), + "queryParameters" | "query_parameters" => Ok(GeneratedField::QueryParameters), "remoteAddress" | "remote_address" => Ok(GeneratedField::RemoteAddress), "genericKey" | "generic_key" => Ok(GeneratedField::GenericKey), "headerValueMatch" | "header_value_match" => Ok(GeneratedField::HeaderValueMatch), @@ -1846,6 +1889,13 @@ impl<'de> serde::Deserialize<'de> for rate_limit::Action { return Err(serde::de::Error::duplicate_field("requestHeaders")); } action_specifier__ = map_.next_value::<::std::option::Option<_>>()?.map(rate_limit::action::ActionSpecifier::RequestHeaders) +; + } + GeneratedField::QueryParameters => { + if action_specifier__.is_some() { + return Err(serde::de::Error::duplicate_field("queryParameters")); + } + action_specifier__ = map_.next_value::<::std::option::Option<_>>()?.map(rate_limit::action::ActionSpecifier::QueryParameters) ; } GeneratedField::RemoteAddress => { @@ -2860,6 +2910,134 @@ impl<'de> serde::Deserialize<'de> for rate_limit::action::QueryParameterValueMat deserializer.deserialize_struct("envoy.config.route.v3.RateLimit.Action.QueryParameterValueMatch", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for rate_limit::action::QueryParameters { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.query_parameter_name.is_empty() { + len += 1; + } + if !self.descriptor_key.is_empty() { + len += 1; + } + if self.skip_if_absent { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.config.route.v3.RateLimit.Action.QueryParameters", len)?; + if !self.query_parameter_name.is_empty() { + struct_ser.serialize_field("query_parameter_name", &self.query_parameter_name)?; + } + if !self.descriptor_key.is_empty() { + struct_ser.serialize_field("descriptor_key", &self.descriptor_key)?; + } + if self.skip_if_absent { + struct_ser.serialize_field("skip_if_absent", &self.skip_if_absent)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for rate_limit::action::QueryParameters { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "query_parameter_name", + "queryParameterName", + "descriptor_key", + "descriptorKey", + "skip_if_absent", + "skipIfAbsent", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + QueryParameterName, + DescriptorKey, + SkipIfAbsent, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "queryParameterName" | "query_parameter_name" => Ok(GeneratedField::QueryParameterName), + "descriptorKey" | "descriptor_key" => Ok(GeneratedField::DescriptorKey), + "skipIfAbsent" | "skip_if_absent" => Ok(GeneratedField::SkipIfAbsent), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = rate_limit::action::QueryParameters; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.config.route.v3.RateLimit.Action.QueryParameters") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut query_parameter_name__ = None; + let mut descriptor_key__ = None; + let mut skip_if_absent__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::QueryParameterName => { + if query_parameter_name__.is_some() { + return Err(serde::de::Error::duplicate_field("queryParameterName")); + } + query_parameter_name__ = Some(map_.next_value()?); + } + GeneratedField::DescriptorKey => { + if descriptor_key__.is_some() { + return Err(serde::de::Error::duplicate_field("descriptorKey")); + } + descriptor_key__ = Some(map_.next_value()?); + } + GeneratedField::SkipIfAbsent => { + if skip_if_absent__.is_some() { + return Err(serde::de::Error::duplicate_field("skipIfAbsent")); + } + skip_if_absent__ = Some(map_.next_value()?); + } + } + } + Ok(rate_limit::action::QueryParameters { + query_parameter_name: query_parameter_name__.unwrap_or_default(), + descriptor_key: descriptor_key__.unwrap_or_default(), + skip_if_absent: skip_if_absent__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.config.route.v3.RateLimit.Action.QueryParameters", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for rate_limit::action::RemoteAddress { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -3130,6 +3308,114 @@ impl<'de> serde::Deserialize<'de> for rate_limit::action::SourceCluster { deserializer.deserialize_struct("envoy.config.route.v3.RateLimit.Action.SourceCluster", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for rate_limit::HitsAddend { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.number.is_some() { + len += 1; + } + if !self.format.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.config.route.v3.RateLimit.HitsAddend", len)?; + if let Some(v) = self.number.as_ref() { + struct_ser.serialize_field("number", v)?; + } + if !self.format.is_empty() { + struct_ser.serialize_field("format", &self.format)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for rate_limit::HitsAddend { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "number", + "format", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Number, + Format, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "number" => Ok(GeneratedField::Number), + "format" => Ok(GeneratedField::Format), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = rate_limit::HitsAddend; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.config.route.v3.RateLimit.HitsAddend") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut number__ = None; + let mut format__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Number => { + if number__.is_some() { + return Err(serde::de::Error::duplicate_field("number")); + } + number__ = map_.next_value()?; + } + GeneratedField::Format => { + if format__.is_some() { + return Err(serde::de::Error::duplicate_field("format")); + } + format__ = Some(map_.next_value()?); + } + } + } + Ok(rate_limit::HitsAddend { + number: number__, + format: format__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.config.route.v3.RateLimit.HitsAddend", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for rate_limit::Override { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -7580,6 +7866,9 @@ impl serde::Serialize for RouteMatch { if !self.dynamic_metadata.is_empty() { len += 1; } + if !self.filter_state.is_empty() { + len += 1; + } if self.path_specifier.is_some() { len += 1; } @@ -7605,6 +7894,9 @@ impl serde::Serialize for RouteMatch { if !self.dynamic_metadata.is_empty() { struct_ser.serialize_field("dynamic_metadata", &self.dynamic_metadata)?; } + if !self.filter_state.is_empty() { + struct_ser.serialize_field("filter_state", &self.filter_state)?; + } if let Some(v) = self.path_specifier.as_ref() { match v { route_match::PathSpecifier::Prefix(v) => { @@ -7649,6 +7941,8 @@ impl<'de> serde::Deserialize<'de> for RouteMatch { "tlsContext", "dynamic_metadata", "dynamicMetadata", + "filter_state", + "filterState", "prefix", "path", "safe_regex", @@ -7670,6 +7964,7 @@ impl<'de> serde::Deserialize<'de> for RouteMatch { Grpc, TlsContext, DynamicMetadata, + FilterState, Prefix, Path, SafeRegex, @@ -7704,6 +7999,7 @@ impl<'de> serde::Deserialize<'de> for RouteMatch { "grpc" => Ok(GeneratedField::Grpc), "tlsContext" | "tls_context" => Ok(GeneratedField::TlsContext), "dynamicMetadata" | "dynamic_metadata" => Ok(GeneratedField::DynamicMetadata), + "filterState" | "filter_state" => Ok(GeneratedField::FilterState), "prefix" => Ok(GeneratedField::Prefix), "path" => Ok(GeneratedField::Path), "safeRegex" | "safe_regex" => Ok(GeneratedField::SafeRegex), @@ -7736,6 +8032,7 @@ impl<'de> serde::Deserialize<'de> for RouteMatch { let mut grpc__ = None; let mut tls_context__ = None; let mut dynamic_metadata__ = None; + let mut filter_state__ = None; let mut path_specifier__ = None; while let Some(k) = map_.next_key()? { match k { @@ -7781,6 +8078,12 @@ impl<'de> serde::Deserialize<'de> for RouteMatch { } dynamic_metadata__ = Some(map_.next_value()?); } + GeneratedField::FilterState => { + if filter_state__.is_some() { + return Err(serde::de::Error::duplicate_field("filterState")); + } + filter_state__ = Some(map_.next_value()?); + } GeneratedField::Prefix => { if path_specifier__.is_some() { return Err(serde::de::Error::duplicate_field("prefix")); @@ -7830,6 +8133,7 @@ impl<'de> serde::Deserialize<'de> for RouteMatch { grpc: grpc__, tls_context: tls_context__, dynamic_metadata: dynamic_metadata__.unwrap_or_default(), + filter_state: filter_state__.unwrap_or_default(), path_specifier: path_specifier__, }) } diff --git a/src/generated/envoy.config.tap.v3.rs b/src/generated/envoy.config.tap.v3.rs index 0ea127a..d70bd1b 100644 --- a/src/generated/envoy.config.tap.v3.rs +++ b/src/generated/envoy.config.tap.v3.rs @@ -199,6 +199,7 @@ impl ::prost::Name for HttpGenericBodyMatch { } } /// Tap output configuration. +/// \[#next-free-field: 6\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct OutputConfig { /// Output sinks for tap data. Currently a single sink is allowed in the list. Once multiple @@ -229,6 +230,14 @@ pub struct OutputConfig { /// ` documentation for more information. #[prost(bool, tag = "4")] pub streaming: bool, + /// Tapped messages will be sent on each read/write event for streamed tapping by default. + /// But this behavior could be controlled by setting this field. + /// If set then the tapped messages will be send once the threshold is reached. + /// This could be used to avoid high frequent sending. + #[prost(message, optional, tag = "5")] + pub min_streamed_sent_bytes: ::core::option::Option< + super::super::super::super::google::protobuf::UInt32Value, + >, } impl ::prost::Name for OutputConfig { const NAME: &'static str = "OutputConfig"; diff --git a/src/generated/envoy.config.tap.v3.serde.rs b/src/generated/envoy.config.tap.v3.serde.rs index 78be284..274f149 100644 --- a/src/generated/envoy.config.tap.v3.serde.rs +++ b/src/generated/envoy.config.tap.v3.serde.rs @@ -849,6 +849,9 @@ impl serde::Serialize for OutputConfig { if self.streaming { len += 1; } + if self.min_streamed_sent_bytes.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.config.tap.v3.OutputConfig", len)?; if !self.sinks.is_empty() { struct_ser.serialize_field("sinks", &self.sinks)?; @@ -862,6 +865,9 @@ impl serde::Serialize for OutputConfig { if self.streaming { struct_ser.serialize_field("streaming", &self.streaming)?; } + if let Some(v) = self.min_streamed_sent_bytes.as_ref() { + struct_ser.serialize_field("min_streamed_sent_bytes", v)?; + } struct_ser.end() } } @@ -878,6 +884,8 @@ impl<'de> serde::Deserialize<'de> for OutputConfig { "max_buffered_tx_bytes", "maxBufferedTxBytes", "streaming", + "min_streamed_sent_bytes", + "minStreamedSentBytes", ]; #[allow(clippy::enum_variant_names)] @@ -886,6 +894,7 @@ impl<'de> serde::Deserialize<'de> for OutputConfig { MaxBufferedRxBytes, MaxBufferedTxBytes, Streaming, + MinStreamedSentBytes, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -911,6 +920,7 @@ impl<'de> serde::Deserialize<'de> for OutputConfig { "maxBufferedRxBytes" | "max_buffered_rx_bytes" => Ok(GeneratedField::MaxBufferedRxBytes), "maxBufferedTxBytes" | "max_buffered_tx_bytes" => Ok(GeneratedField::MaxBufferedTxBytes), "streaming" => Ok(GeneratedField::Streaming), + "minStreamedSentBytes" | "min_streamed_sent_bytes" => Ok(GeneratedField::MinStreamedSentBytes), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -934,6 +944,7 @@ impl<'de> serde::Deserialize<'de> for OutputConfig { let mut max_buffered_rx_bytes__ = None; let mut max_buffered_tx_bytes__ = None; let mut streaming__ = None; + let mut min_streamed_sent_bytes__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Sinks => { @@ -960,6 +971,12 @@ impl<'de> serde::Deserialize<'de> for OutputConfig { } streaming__ = Some(map_.next_value()?); } + GeneratedField::MinStreamedSentBytes => { + if min_streamed_sent_bytes__.is_some() { + return Err(serde::de::Error::duplicate_field("minStreamedSentBytes")); + } + min_streamed_sent_bytes__ = map_.next_value()?; + } } } Ok(OutputConfig { @@ -967,6 +984,7 @@ impl<'de> serde::Deserialize<'de> for OutputConfig { max_buffered_rx_bytes: max_buffered_rx_bytes__, max_buffered_tx_bytes: max_buffered_tx_bytes__, streaming: streaming__.unwrap_or_default(), + min_streamed_sent_bytes: min_streamed_sent_bytes__, }) } } diff --git a/src/generated/envoy.config.trace.v3.rs b/src/generated/envoy.config.trace.v3.rs index a4873f0..fcd74b9 100644 --- a/src/generated/envoy.config.trace.v3.rs +++ b/src/generated/envoy.config.trace.v3.rs @@ -65,6 +65,26 @@ impl ::prost::Name for Tracing { "type.googleapis.com/envoy.config.trace.v3.Tracing".into() } } +/// Configuration for the Remote Configuration feature. +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct DatadogRemoteConfig { + /// Frequency at which new configuration updates are queried. + /// If no value is provided, the default value is delegated to the Datadog tracing library. + #[prost(message, optional, tag = "1")] + pub polling_interval: ::core::option::Option< + super::super::super::super::google::protobuf::Duration, + >, +} +impl ::prost::Name for DatadogRemoteConfig { + const NAME: &'static str = "DatadogRemoteConfig"; + const PACKAGE: &'static str = "envoy.config.trace.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.config.trace.v3.DatadogRemoteConfig".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.config.trace.v3.DatadogRemoteConfig".into() + } +} /// Configuration for the Datadog tracer. /// \[#extension: envoy.tracers.datadog\] #[derive(Clone, PartialEq, ::prost::Message)] @@ -79,6 +99,13 @@ pub struct DatadogConfig { /// that require a specific hostname. Defaults to :ref:`collector_cluster ` above. #[prost(string, tag = "3")] pub collector_hostname: ::prost::alloc::string::String, + /// Enables and configures remote configuration. + /// Remote Configuration allows to configure the tracer from Datadog's user interface. + /// This feature can drastically increase the number of connections to the Datadog Agent. + /// Each tracer regularly polls for configuration updates, and the number of tracers is the product + /// of the number of listeners and worker threads. + #[prost(message, optional, tag = "4")] + pub remote_config: ::core::option::Option, } impl ::prost::Name for DatadogConfig { const NAME: &'static str = "DatadogConfig"; @@ -90,10 +117,10 @@ impl ::prost::Name for DatadogConfig { "type.googleapis.com/envoy.config.trace.v3.DatadogConfig".into() } } -/// DynamicOtConfig is used to dynamically load a tracer from a shared library +/// DynamicOtConfig was used to dynamically load a tracer from a shared library /// that implements the `OpenTracing dynamic loading API /// <`_.> -/// \[#extension: envoy.tracers.dynamic_ot\] +/// \[#not-implemented-hide:\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct DynamicOtConfig { /// Dynamic library implementing the `OpenTracing API @@ -204,162 +231,9 @@ impl ::prost::Name for LightstepConfig { "type.googleapis.com/envoy.config.trace.v3.LightstepConfig".into() } } -/// Configuration for the OpenCensus tracer. -/// \[#next-free-field: 15\] -/// \[#extension: envoy.tracers.opencensus\] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct OpenCensusConfig { - /// Configures tracing, e.g. the sampler, max number of annotations, etc. - #[deprecated] - #[prost(message, optional, tag = "1")] - pub trace_config: ::core::option::Option< - super::super::super::super::opencensus::proto::trace::v1::TraceConfig, - >, - /// Enables the stdout exporter if set to true. This is intended for debugging - /// purposes. - #[deprecated] - #[prost(bool, tag = "2")] - pub stdout_exporter_enabled: bool, - /// Enables the Stackdriver exporter if set to true. The project_id must also - /// be set. - #[deprecated] - #[prost(bool, tag = "3")] - pub stackdriver_exporter_enabled: bool, - /// The Cloud project_id to use for Stackdriver tracing. - #[deprecated] - #[prost(string, tag = "4")] - pub stackdriver_project_id: ::prost::alloc::string::String, - /// (optional) By default, the Stackdriver exporter will connect to production - /// Stackdriver. If stackdriver_address is non-empty, it will instead connect - /// to this address, which is in the gRPC format: - /// - #[deprecated] - #[prost(string, tag = "10")] - pub stackdriver_address: ::prost::alloc::string::String, - /// (optional) The gRPC server that hosts Stackdriver tracing service. Only - /// Google gRPC is supported. If :ref:`target_uri ` - /// is not provided, the default production Stackdriver address will be used. - #[deprecated] - #[prost(message, optional, tag = "13")] - pub stackdriver_grpc_service: ::core::option::Option< - super::super::core::v3::GrpcService, - >, - /// Enables the Zipkin exporter if set to true. The url and service name must - /// also be set. This is deprecated, prefer to use Envoy's :ref:`native Zipkin - /// tracer `. - #[deprecated] - #[prost(bool, tag = "5")] - pub zipkin_exporter_enabled: bool, - /// The URL to Zipkin, e.g. " This is - /// deprecated, prefer to use Envoy's :ref:`native Zipkin tracer - /// `. - #[deprecated] - #[prost(string, tag = "6")] - pub zipkin_url: ::prost::alloc::string::String, - /// Enables the OpenCensus Agent exporter if set to true. The ocagent_address or - /// ocagent_grpc_service must also be set. - #[deprecated] - #[prost(bool, tag = "11")] - pub ocagent_exporter_enabled: bool, - /// The address of the OpenCensus Agent, if its exporter is enabled, in gRPC - /// format: - /// \[#comment:TODO: deprecate this field\] - #[deprecated] - #[prost(string, tag = "12")] - pub ocagent_address: ::prost::alloc::string::String, - /// (optional) The gRPC server hosted by the OpenCensus Agent. Only Google gRPC is supported. - /// This is only used if the ocagent_address is left empty. - #[deprecated] - #[prost(message, optional, tag = "14")] - pub ocagent_grpc_service: ::core::option::Option< - super::super::core::v3::GrpcService, - >, - /// List of incoming trace context headers we will accept. First one found - /// wins. - #[deprecated] - #[prost( - enumeration = "open_census_config::TraceContext", - repeated, - packed = "false", - tag = "8" - )] - pub incoming_trace_context: ::prost::alloc::vec::Vec, - /// List of outgoing trace context headers we will produce. - #[deprecated] - #[prost( - enumeration = "open_census_config::TraceContext", - repeated, - packed = "false", - tag = "9" - )] - pub outgoing_trace_context: ::prost::alloc::vec::Vec, -} -/// Nested message and enum types in `OpenCensusConfig`. -pub mod open_census_config { - #[derive( - Clone, - Copy, - Debug, - PartialEq, - Eq, - Hash, - PartialOrd, - Ord, - ::prost::Enumeration - )] - #[repr(i32)] - pub enum TraceContext { - /// No-op default, no trace context is utilized. - None = 0, - /// W3C Trace-Context format "traceparent:" header. - TraceContext = 1, - /// Binary "grpc-trace-bin:" header. - GrpcTraceBin = 2, - /// "X-Cloud-Trace-Context:" header. - CloudTraceContext = 3, - /// X-B3-* headers. - B3 = 4, - } - impl TraceContext { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - Self::None => "NONE", - Self::TraceContext => "TRACE_CONTEXT", - Self::GrpcTraceBin => "GRPC_TRACE_BIN", - Self::CloudTraceContext => "CLOUD_TRACE_CONTEXT", - Self::B3 => "B3", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "NONE" => Some(Self::None), - "TRACE_CONTEXT" => Some(Self::TraceContext), - "GRPC_TRACE_BIN" => Some(Self::GrpcTraceBin), - "CLOUD_TRACE_CONTEXT" => Some(Self::CloudTraceContext), - "B3" => Some(Self::B3), - _ => None, - } - } - } -} -impl ::prost::Name for OpenCensusConfig { - const NAME: &'static str = "OpenCensusConfig"; - const PACKAGE: &'static str = "envoy.config.trace.v3"; - fn full_name() -> ::prost::alloc::string::String { - "envoy.config.trace.v3.OpenCensusConfig".into() - } - fn type_url() -> ::prost::alloc::string::String { - "type.googleapis.com/envoy.config.trace.v3.OpenCensusConfig".into() - } -} /// Configuration for the OpenTelemetry tracer. /// \[#extension: envoy.tracers.opentelemetry\] -/// \[#next-free-field: 6\] +/// \[#next-free-field: 7\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct OpenTelemetryConfig { /// The upstream gRPC cluster that will receive OTLP traces. @@ -399,6 +273,13 @@ pub struct OpenTelemetryConfig { /// \[#extension-category: envoy.tracers.opentelemetry.samplers\] #[prost(message, optional, tag = "5")] pub sampler: ::core::option::Option, + /// Envoy caches the span in memory when the OpenTelemetry backend service is temporarily unavailable. + /// This field specifies the maximum number of spans that can be cached. If not specified, the + /// default is 1024. + #[prost(message, optional, tag = "6")] + pub max_cache_size: ::core::option::Option< + super::super::super::super::google::protobuf::UInt32Value, + >, } impl ::prost::Name for OpenTelemetryConfig { const NAME: &'static str = "OpenTelemetryConfig"; diff --git a/src/generated/envoy.config.trace.v3.serde.rs b/src/generated/envoy.config.trace.v3.serde.rs index 2a8c3e1..ed06d45 100644 --- a/src/generated/envoy.config.trace.v3.serde.rs +++ b/src/generated/envoy.config.trace.v3.serde.rs @@ -165,6 +165,9 @@ impl serde::Serialize for DatadogConfig { if !self.collector_hostname.is_empty() { len += 1; } + if self.remote_config.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.config.trace.v3.DatadogConfig", len)?; if !self.collector_cluster.is_empty() { struct_ser.serialize_field("collector_cluster", &self.collector_cluster)?; @@ -175,6 +178,9 @@ impl serde::Serialize for DatadogConfig { if !self.collector_hostname.is_empty() { struct_ser.serialize_field("collector_hostname", &self.collector_hostname)?; } + if let Some(v) = self.remote_config.as_ref() { + struct_ser.serialize_field("remote_config", v)?; + } struct_ser.end() } } @@ -191,6 +197,8 @@ impl<'de> serde::Deserialize<'de> for DatadogConfig { "serviceName", "collector_hostname", "collectorHostname", + "remote_config", + "remoteConfig", ]; #[allow(clippy::enum_variant_names)] @@ -198,6 +206,7 @@ impl<'de> serde::Deserialize<'de> for DatadogConfig { CollectorCluster, ServiceName, CollectorHostname, + RemoteConfig, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -222,6 +231,7 @@ impl<'de> serde::Deserialize<'de> for DatadogConfig { "collectorCluster" | "collector_cluster" => Ok(GeneratedField::CollectorCluster), "serviceName" | "service_name" => Ok(GeneratedField::ServiceName), "collectorHostname" | "collector_hostname" => Ok(GeneratedField::CollectorHostname), + "remoteConfig" | "remote_config" => Ok(GeneratedField::RemoteConfig), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -244,6 +254,7 @@ impl<'de> serde::Deserialize<'de> for DatadogConfig { let mut collector_cluster__ = None; let mut service_name__ = None; let mut collector_hostname__ = None; + let mut remote_config__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::CollectorCluster => { @@ -264,18 +275,117 @@ impl<'de> serde::Deserialize<'de> for DatadogConfig { } collector_hostname__ = Some(map_.next_value()?); } + GeneratedField::RemoteConfig => { + if remote_config__.is_some() { + return Err(serde::de::Error::duplicate_field("remoteConfig")); + } + remote_config__ = map_.next_value()?; + } } } Ok(DatadogConfig { collector_cluster: collector_cluster__.unwrap_or_default(), service_name: service_name__.unwrap_or_default(), collector_hostname: collector_hostname__.unwrap_or_default(), + remote_config: remote_config__, }) } } deserializer.deserialize_struct("envoy.config.trace.v3.DatadogConfig", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for DatadogRemoteConfig { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.polling_interval.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.config.trace.v3.DatadogRemoteConfig", len)?; + if let Some(v) = self.polling_interval.as_ref() { + struct_ser.serialize_field("polling_interval", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for DatadogRemoteConfig { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "polling_interval", + "pollingInterval", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + PollingInterval, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "pollingInterval" | "polling_interval" => Ok(GeneratedField::PollingInterval), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = DatadogRemoteConfig; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.config.trace.v3.DatadogRemoteConfig") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut polling_interval__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::PollingInterval => { + if polling_interval__.is_some() { + return Err(serde::de::Error::duplicate_field("pollingInterval")); + } + polling_interval__ = map_.next_value()?; + } + } + } + Ok(DatadogRemoteConfig { + polling_interval: polling_interval__, + }) + } + } + deserializer.deserialize_struct("envoy.config.trace.v3.DatadogRemoteConfig", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for DynamicOtConfig { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -611,402 +721,6 @@ impl<'de> serde::Deserialize<'de> for lightstep_config::PropagationMode { deserializer.deserialize_any(GeneratedVisitor) } } -impl serde::Serialize for OpenCensusConfig { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.trace_config.is_some() { - len += 1; - } - if self.stdout_exporter_enabled { - len += 1; - } - if self.stackdriver_exporter_enabled { - len += 1; - } - if !self.stackdriver_project_id.is_empty() { - len += 1; - } - if !self.stackdriver_address.is_empty() { - len += 1; - } - if self.stackdriver_grpc_service.is_some() { - len += 1; - } - if self.zipkin_exporter_enabled { - len += 1; - } - if !self.zipkin_url.is_empty() { - len += 1; - } - if self.ocagent_exporter_enabled { - len += 1; - } - if !self.ocagent_address.is_empty() { - len += 1; - } - if self.ocagent_grpc_service.is_some() { - len += 1; - } - if !self.incoming_trace_context.is_empty() { - len += 1; - } - if !self.outgoing_trace_context.is_empty() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("envoy.config.trace.v3.OpenCensusConfig", len)?; - if let Some(v) = self.trace_config.as_ref() { - struct_ser.serialize_field("trace_config", v)?; - } - if self.stdout_exporter_enabled { - struct_ser.serialize_field("stdout_exporter_enabled", &self.stdout_exporter_enabled)?; - } - if self.stackdriver_exporter_enabled { - struct_ser.serialize_field("stackdriver_exporter_enabled", &self.stackdriver_exporter_enabled)?; - } - if !self.stackdriver_project_id.is_empty() { - struct_ser.serialize_field("stackdriver_project_id", &self.stackdriver_project_id)?; - } - if !self.stackdriver_address.is_empty() { - struct_ser.serialize_field("stackdriver_address", &self.stackdriver_address)?; - } - if let Some(v) = self.stackdriver_grpc_service.as_ref() { - struct_ser.serialize_field("stackdriver_grpc_service", v)?; - } - if self.zipkin_exporter_enabled { - struct_ser.serialize_field("zipkin_exporter_enabled", &self.zipkin_exporter_enabled)?; - } - if !self.zipkin_url.is_empty() { - struct_ser.serialize_field("zipkin_url", &self.zipkin_url)?; - } - if self.ocagent_exporter_enabled { - struct_ser.serialize_field("ocagent_exporter_enabled", &self.ocagent_exporter_enabled)?; - } - if !self.ocagent_address.is_empty() { - struct_ser.serialize_field("ocagent_address", &self.ocagent_address)?; - } - if let Some(v) = self.ocagent_grpc_service.as_ref() { - struct_ser.serialize_field("ocagent_grpc_service", v)?; - } - if !self.incoming_trace_context.is_empty() { - let v = self.incoming_trace_context.iter().cloned().map(|v| { - open_census_config::TraceContext::try_from(v) - .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", v))) - }).collect::, _>>()?; - struct_ser.serialize_field("incoming_trace_context", &v)?; - } - if !self.outgoing_trace_context.is_empty() { - let v = self.outgoing_trace_context.iter().cloned().map(|v| { - open_census_config::TraceContext::try_from(v) - .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", v))) - }).collect::, _>>()?; - struct_ser.serialize_field("outgoing_trace_context", &v)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for OpenCensusConfig { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "trace_config", - "traceConfig", - "stdout_exporter_enabled", - "stdoutExporterEnabled", - "stackdriver_exporter_enabled", - "stackdriverExporterEnabled", - "stackdriver_project_id", - "stackdriverProjectId", - "stackdriver_address", - "stackdriverAddress", - "stackdriver_grpc_service", - "stackdriverGrpcService", - "zipkin_exporter_enabled", - "zipkinExporterEnabled", - "zipkin_url", - "zipkinUrl", - "ocagent_exporter_enabled", - "ocagentExporterEnabled", - "ocagent_address", - "ocagentAddress", - "ocagent_grpc_service", - "ocagentGrpcService", - "incoming_trace_context", - "incomingTraceContext", - "outgoing_trace_context", - "outgoingTraceContext", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - TraceConfig, - StdoutExporterEnabled, - StackdriverExporterEnabled, - StackdriverProjectId, - StackdriverAddress, - StackdriverGrpcService, - ZipkinExporterEnabled, - ZipkinUrl, - OcagentExporterEnabled, - OcagentAddress, - OcagentGrpcService, - IncomingTraceContext, - OutgoingTraceContext, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "traceConfig" | "trace_config" => Ok(GeneratedField::TraceConfig), - "stdoutExporterEnabled" | "stdout_exporter_enabled" => Ok(GeneratedField::StdoutExporterEnabled), - "stackdriverExporterEnabled" | "stackdriver_exporter_enabled" => Ok(GeneratedField::StackdriverExporterEnabled), - "stackdriverProjectId" | "stackdriver_project_id" => Ok(GeneratedField::StackdriverProjectId), - "stackdriverAddress" | "stackdriver_address" => Ok(GeneratedField::StackdriverAddress), - "stackdriverGrpcService" | "stackdriver_grpc_service" => Ok(GeneratedField::StackdriverGrpcService), - "zipkinExporterEnabled" | "zipkin_exporter_enabled" => Ok(GeneratedField::ZipkinExporterEnabled), - "zipkinUrl" | "zipkin_url" => Ok(GeneratedField::ZipkinUrl), - "ocagentExporterEnabled" | "ocagent_exporter_enabled" => Ok(GeneratedField::OcagentExporterEnabled), - "ocagentAddress" | "ocagent_address" => Ok(GeneratedField::OcagentAddress), - "ocagentGrpcService" | "ocagent_grpc_service" => Ok(GeneratedField::OcagentGrpcService), - "incomingTraceContext" | "incoming_trace_context" => Ok(GeneratedField::IncomingTraceContext), - "outgoingTraceContext" | "outgoing_trace_context" => Ok(GeneratedField::OutgoingTraceContext), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = OpenCensusConfig; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct envoy.config.trace.v3.OpenCensusConfig") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut trace_config__ = None; - let mut stdout_exporter_enabled__ = None; - let mut stackdriver_exporter_enabled__ = None; - let mut stackdriver_project_id__ = None; - let mut stackdriver_address__ = None; - let mut stackdriver_grpc_service__ = None; - let mut zipkin_exporter_enabled__ = None; - let mut zipkin_url__ = None; - let mut ocagent_exporter_enabled__ = None; - let mut ocagent_address__ = None; - let mut ocagent_grpc_service__ = None; - let mut incoming_trace_context__ = None; - let mut outgoing_trace_context__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::TraceConfig => { - if trace_config__.is_some() { - return Err(serde::de::Error::duplicate_field("traceConfig")); - } - trace_config__ = map_.next_value()?; - } - GeneratedField::StdoutExporterEnabled => { - if stdout_exporter_enabled__.is_some() { - return Err(serde::de::Error::duplicate_field("stdoutExporterEnabled")); - } - stdout_exporter_enabled__ = Some(map_.next_value()?); - } - GeneratedField::StackdriverExporterEnabled => { - if stackdriver_exporter_enabled__.is_some() { - return Err(serde::de::Error::duplicate_field("stackdriverExporterEnabled")); - } - stackdriver_exporter_enabled__ = Some(map_.next_value()?); - } - GeneratedField::StackdriverProjectId => { - if stackdriver_project_id__.is_some() { - return Err(serde::de::Error::duplicate_field("stackdriverProjectId")); - } - stackdriver_project_id__ = Some(map_.next_value()?); - } - GeneratedField::StackdriverAddress => { - if stackdriver_address__.is_some() { - return Err(serde::de::Error::duplicate_field("stackdriverAddress")); - } - stackdriver_address__ = Some(map_.next_value()?); - } - GeneratedField::StackdriverGrpcService => { - if stackdriver_grpc_service__.is_some() { - return Err(serde::de::Error::duplicate_field("stackdriverGrpcService")); - } - stackdriver_grpc_service__ = map_.next_value()?; - } - GeneratedField::ZipkinExporterEnabled => { - if zipkin_exporter_enabled__.is_some() { - return Err(serde::de::Error::duplicate_field("zipkinExporterEnabled")); - } - zipkin_exporter_enabled__ = Some(map_.next_value()?); - } - GeneratedField::ZipkinUrl => { - if zipkin_url__.is_some() { - return Err(serde::de::Error::duplicate_field("zipkinUrl")); - } - zipkin_url__ = Some(map_.next_value()?); - } - GeneratedField::OcagentExporterEnabled => { - if ocagent_exporter_enabled__.is_some() { - return Err(serde::de::Error::duplicate_field("ocagentExporterEnabled")); - } - ocagent_exporter_enabled__ = Some(map_.next_value()?); - } - GeneratedField::OcagentAddress => { - if ocagent_address__.is_some() { - return Err(serde::de::Error::duplicate_field("ocagentAddress")); - } - ocagent_address__ = Some(map_.next_value()?); - } - GeneratedField::OcagentGrpcService => { - if ocagent_grpc_service__.is_some() { - return Err(serde::de::Error::duplicate_field("ocagentGrpcService")); - } - ocagent_grpc_service__ = map_.next_value()?; - } - GeneratedField::IncomingTraceContext => { - if incoming_trace_context__.is_some() { - return Err(serde::de::Error::duplicate_field("incomingTraceContext")); - } - incoming_trace_context__ = Some(map_.next_value::>()?.into_iter().map(|x| x as i32).collect()); - } - GeneratedField::OutgoingTraceContext => { - if outgoing_trace_context__.is_some() { - return Err(serde::de::Error::duplicate_field("outgoingTraceContext")); - } - outgoing_trace_context__ = Some(map_.next_value::>()?.into_iter().map(|x| x as i32).collect()); - } - } - } - Ok(OpenCensusConfig { - trace_config: trace_config__, - stdout_exporter_enabled: stdout_exporter_enabled__.unwrap_or_default(), - stackdriver_exporter_enabled: stackdriver_exporter_enabled__.unwrap_or_default(), - stackdriver_project_id: stackdriver_project_id__.unwrap_or_default(), - stackdriver_address: stackdriver_address__.unwrap_or_default(), - stackdriver_grpc_service: stackdriver_grpc_service__, - zipkin_exporter_enabled: zipkin_exporter_enabled__.unwrap_or_default(), - zipkin_url: zipkin_url__.unwrap_or_default(), - ocagent_exporter_enabled: ocagent_exporter_enabled__.unwrap_or_default(), - ocagent_address: ocagent_address__.unwrap_or_default(), - ocagent_grpc_service: ocagent_grpc_service__, - incoming_trace_context: incoming_trace_context__.unwrap_or_default(), - outgoing_trace_context: outgoing_trace_context__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("envoy.config.trace.v3.OpenCensusConfig", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for open_census_config::TraceContext { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - let variant = match self { - Self::None => "NONE", - Self::TraceContext => "TRACE_CONTEXT", - Self::GrpcTraceBin => "GRPC_TRACE_BIN", - Self::CloudTraceContext => "CLOUD_TRACE_CONTEXT", - Self::B3 => "B3", - }; - serializer.serialize_str(variant) - } -} -impl<'de> serde::Deserialize<'de> for open_census_config::TraceContext { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "NONE", - "TRACE_CONTEXT", - "GRPC_TRACE_BIN", - "CLOUD_TRACE_CONTEXT", - "B3", - ]; - - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = open_census_config::TraceContext; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - fn visit_i64(self, v: i64) -> std::result::Result - where - E: serde::de::Error, - { - i32::try_from(v) - .ok() - .and_then(|x| x.try_into().ok()) - .ok_or_else(|| { - serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) - }) - } - - fn visit_u64(self, v: u64) -> std::result::Result - where - E: serde::de::Error, - { - i32::try_from(v) - .ok() - .and_then(|x| x.try_into().ok()) - .ok_or_else(|| { - serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) - }) - } - - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "NONE" => Ok(open_census_config::TraceContext::None), - "TRACE_CONTEXT" => Ok(open_census_config::TraceContext::TraceContext), - "GRPC_TRACE_BIN" => Ok(open_census_config::TraceContext::GrpcTraceBin), - "CLOUD_TRACE_CONTEXT" => Ok(open_census_config::TraceContext::CloudTraceContext), - "B3" => Ok(open_census_config::TraceContext::B3), - _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), - } - } - } - deserializer.deserialize_any(GeneratedVisitor) - } -} impl serde::Serialize for OpenTelemetryConfig { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -1030,6 +744,9 @@ impl serde::Serialize for OpenTelemetryConfig { if self.sampler.is_some() { len += 1; } + if self.max_cache_size.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.config.trace.v3.OpenTelemetryConfig", len)?; if let Some(v) = self.grpc_service.as_ref() { struct_ser.serialize_field("grpc_service", v)?; @@ -1046,6 +763,9 @@ impl serde::Serialize for OpenTelemetryConfig { if let Some(v) = self.sampler.as_ref() { struct_ser.serialize_field("sampler", v)?; } + if let Some(v) = self.max_cache_size.as_ref() { + struct_ser.serialize_field("max_cache_size", v)?; + } struct_ser.end() } } @@ -1065,6 +785,8 @@ impl<'de> serde::Deserialize<'de> for OpenTelemetryConfig { "resource_detectors", "resourceDetectors", "sampler", + "max_cache_size", + "maxCacheSize", ]; #[allow(clippy::enum_variant_names)] @@ -1074,6 +796,7 @@ impl<'de> serde::Deserialize<'de> for OpenTelemetryConfig { ServiceName, ResourceDetectors, Sampler, + MaxCacheSize, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -1100,6 +823,7 @@ impl<'de> serde::Deserialize<'de> for OpenTelemetryConfig { "serviceName" | "service_name" => Ok(GeneratedField::ServiceName), "resourceDetectors" | "resource_detectors" => Ok(GeneratedField::ResourceDetectors), "sampler" => Ok(GeneratedField::Sampler), + "maxCacheSize" | "max_cache_size" => Ok(GeneratedField::MaxCacheSize), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -1124,6 +848,7 @@ impl<'de> serde::Deserialize<'de> for OpenTelemetryConfig { let mut service_name__ = None; let mut resource_detectors__ = None; let mut sampler__ = None; + let mut max_cache_size__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::GrpcService => { @@ -1156,6 +881,12 @@ impl<'de> serde::Deserialize<'de> for OpenTelemetryConfig { } sampler__ = map_.next_value()?; } + GeneratedField::MaxCacheSize => { + if max_cache_size__.is_some() { + return Err(serde::de::Error::duplicate_field("maxCacheSize")); + } + max_cache_size__ = map_.next_value()?; + } } } Ok(OpenTelemetryConfig { @@ -1164,6 +895,7 @@ impl<'de> serde::Deserialize<'de> for OpenTelemetryConfig { service_name: service_name__.unwrap_or_default(), resource_detectors: resource_detectors__.unwrap_or_default(), sampler: sampler__, + max_cache_size: max_cache_size__, }) } } diff --git a/src/generated/envoy.data.accesslog.v3.rs b/src/generated/envoy.data.accesslog.v3.rs index a064ad5..5849a0a 100644 --- a/src/generated/envoy.data.accesslog.v3.rs +++ b/src/generated/envoy.data.accesslog.v3.rs @@ -121,8 +121,10 @@ pub struct AccessLogCommon { #[prost(double, tag = "1")] pub sample_rate: f64, /// This field is the remote/origin address on which the request from the user was received. - /// Note: This may not be the physical peer. E.g, if the remote address is inferred from for - /// example the x-forwarder-for header, proxy protocol, etc. + /// + /// .. note:: + /// This may not be the actual peer address. For example, it might be derived from headers like ``x-forwarded-for``, + /// the proxy protocol, or similar sources. #[prost(message, optional, tag = "2")] pub downstream_remote_address: ::core::option::Option< super::super::super::config::core::v3::Address, @@ -132,7 +134,7 @@ pub struct AccessLogCommon { pub downstream_local_address: ::core::option::Option< super::super::super::config::core::v3::Address, >, - /// If the connection is secure,S this field will contain TLS properties. + /// If the connection is secure, this field will contain TLS properties. #[prost(message, optional, tag = "4")] pub tls_properties: ::core::option::Option, /// The time that Envoy started servicing this request. This is effectively the time that the first @@ -148,7 +150,7 @@ pub struct AccessLogCommon { super::super::super::super::google::protobuf::Duration, >, /// Interval between the first downstream byte received and the first upstream byte sent. There may - /// by considerable delta between ``time_to_last_rx_byte`` and this value due to filters. + /// be considerable delta between ``time_to_last_rx_byte`` and this value due to filters. /// Additionally, the same caveats apply as documented in ``time_to_last_downstream_tx_byte`` about /// not accounting for kernel socket buffer time, etc. #[prost(message, optional, tag = "7")] @@ -225,7 +227,7 @@ pub struct AccessLogCommon { /// If upstream connection failed due to transport socket (e.g. TLS handshake), provides the /// failure reason from the transport socket. The format of this field depends on the configured /// upstream transport socket. Common TLS failures are in - /// :ref:`TLS trouble shooting `. + /// :ref:`TLS troubleshooting `. #[prost(string, tag = "18")] pub upstream_transport_failure_reason: ::prost::alloc::string::String, /// The name of the route @@ -247,7 +249,7 @@ pub struct AccessLogCommon { super::super::super::super::google::protobuf::Any, >, /// A list of custom tags, which annotate logs with additional information. - /// To configure this value, users should configure + /// To configure this value, see the documentation for /// :ref:`custom_tags `. #[prost(map = "string, string", tag = "22")] pub custom_tags: ::std::collections::HashMap< @@ -273,40 +275,41 @@ pub struct AccessLogCommon { /// This could be any format string that could be used to identify one stream. #[prost(string, tag = "26")] pub stream_id: ::prost::alloc::string::String, - /// If this log entry is final log entry that flushed after the stream completed or - /// intermediate log entry that flushed periodically during the stream. - /// There may be multiple intermediate log entries and only one final log entry for each - /// long-live stream (TCP connection, long-live HTTP2 stream). - /// And if it is necessary, unique ID or identifier can be added to the log entry - /// :ref:`stream_id ` to - /// correlate all these intermediate log entries and final log entry. + /// Indicates whether this log entry is the final entry (flushed after the stream completed) or an intermediate entry + /// (flushed periodically during the stream). + /// + /// For long-lived streams (e.g., TCP connections or long-lived HTTP/2 streams), there may be multiple intermediate + /// entries and only one final entry. + /// + /// If needed, a unique identifier (see :ref:`stream_id `) + /// can be used to correlate all intermediate and final log entries for the same stream. /// /// .. attention:: /// - /// This field is deprecated in favor of ``access_log_type`` for better indication of the - /// type of the access log record. + /// This field is deprecated in favor of ``access_log_type``, which provides a clearer indication of the log entry + /// type. #[deprecated] #[prost(bool, tag = "27")] pub intermediate_log_entry: bool, /// If downstream connection in listener failed due to transport socket (e.g. TLS handshake), provides the /// failure reason from the transport socket. The format of this field depends on the configured downstream - /// transport socket. Common TLS failures are in :ref:`TLS trouble shooting `. + /// transport socket. Common TLS failures are in :ref:`TLS troubleshooting `. #[prost(string, tag = "28")] pub downstream_transport_failure_reason: ::prost::alloc::string::String, /// For HTTP: Total number of bytes sent to the downstream by the http stream. - /// For TCP: Total number of bytes sent to the downstream by the tcp proxy. + /// For TCP: Total number of bytes sent to the downstream by the :ref:`TCP Proxy `. #[prost(uint64, tag = "29")] pub downstream_wire_bytes_sent: u64, /// For HTTP: Total number of bytes received from the downstream by the http stream. Envoy over counts sizes of received HTTP/1.1 pipelined requests by adding up bytes of requests in the pipeline to the one currently being processed. - /// For TCP: Total number of bytes received from the downstream by the tcp proxy. + /// For TCP: Total number of bytes received from the downstream by the :ref:`TCP Proxy `. #[prost(uint64, tag = "30")] pub downstream_wire_bytes_received: u64, /// For HTTP: Total number of bytes sent to the upstream by the http stream. This value accumulates during upstream retries. - /// For TCP: Total number of bytes sent to the upstream by the tcp proxy. + /// For TCP: Total number of bytes sent to the upstream by the :ref:`TCP Proxy `. #[prost(uint64, tag = "31")] pub upstream_wire_bytes_sent: u64, /// For HTTP: Total number of bytes received from the upstream by the http stream. - /// For TCP: Total number of bytes sent to the upstream by the tcp proxy. + /// For TCP: Total number of bytes sent to the upstream by the :ref:`TCP Proxy `. #[prost(uint64, tag = "32")] pub upstream_wire_bytes_received: u64, /// The type of the access log, which indicates when the log was recorded. @@ -338,7 +341,7 @@ pub struct ResponseFlags { /// Indicates there was no healthy upstream. #[prost(bool, tag = "2")] pub no_healthy_upstream: bool, - /// Indicates an there was an upstream request timeout. + /// Indicates there was an upstream request timeout. #[prost(bool, tag = "3")] pub upstream_request_timeout: bool, /// Indicates local codec level reset was sent on the stream. @@ -399,7 +402,7 @@ pub struct ResponseFlags { /// Indicates that a filter configuration is not available. #[prost(bool, tag = "22")] pub no_filter_config_found: bool, - /// Indicates that request or connection exceeded the downstream connection duration. + /// Indicates that the request or connection exceeded the downstream connection duration. #[prost(bool, tag = "23")] pub duration_timeout: bool, /// Indicates there was an HTTP protocol error in the upstream response. @@ -678,7 +681,7 @@ pub struct HttpRequestProperties { /// do not already have a request ID. #[prost(string, tag = "9")] pub request_id: ::prost::alloc::string::String, - /// Value of the ``X-Envoy-Original-Path`` request header. + /// Value of the ``x-envoy-original-path`` request header. #[prost(string, tag = "10")] pub original_path: ::prost::alloc::string::String, /// Size of the HTTP request headers in bytes. diff --git a/src/generated/envoy.data.tap.v3.rs b/src/generated/envoy.data.tap.v3.rs index 4b3cd5c..b4cec5f 100644 --- a/src/generated/envoy.data.tap.v3.rs +++ b/src/generated/envoy.data.tap.v3.rs @@ -169,6 +169,7 @@ impl ::prost::Name for HttpStreamedTraceSegment { } } /// Event in a socket trace. +/// \[#next-free-field: 6\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct SocketEvent { /// Timestamp for event. @@ -176,6 +177,9 @@ pub struct SocketEvent { pub timestamp: ::core::option::Option< super::super::super::super::google::protobuf::Timestamp, >, + /// Connection information per event + #[prost(message, optional, tag = "5")] + pub connection: ::core::option::Option, /// Read or write with content as bytes string. #[prost(oneof = "socket_event::EventSelector", tags = "2, 3, 4")] pub event_selector: ::core::option::Option, @@ -290,6 +294,22 @@ impl ::prost::Name for SocketBufferedTrace { "type.googleapis.com/envoy.data.tap.v3.SocketBufferedTrace".into() } } +/// A message for the sequence of observed events +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SocketEvents { + #[prost(message, repeated, tag = "1")] + pub events: ::prost::alloc::vec::Vec, +} +impl ::prost::Name for SocketEvents { + const NAME: &'static str = "SocketEvents"; + const PACKAGE: &'static str = "envoy.data.tap.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.data.tap.v3.SocketEvents".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.data.tap.v3.SocketEvents".into() + } +} /// A streamed socket trace segment. Multiple segments make up a full trace. #[derive(Clone, PartialEq, ::prost::Message)] pub struct SocketStreamedTraceSegment { @@ -297,7 +317,7 @@ pub struct SocketStreamedTraceSegment { /// for long term stable uniqueness. Matches connection IDs used in Envoy logs. #[prost(uint64, tag = "1")] pub trace_id: u64, - #[prost(oneof = "socket_streamed_trace_segment::MessagePiece", tags = "2, 3")] + #[prost(oneof = "socket_streamed_trace_segment::MessagePiece", tags = "2, 3, 4")] pub message_piece: ::core::option::Option< socket_streamed_trace_segment::MessagePiece, >, @@ -312,6 +332,9 @@ pub mod socket_streamed_trace_segment { /// Socket event. #[prost(message, tag = "3")] Event(super::SocketEvent), + /// Sequence of observed events. + #[prost(message, tag = "4")] + Events(super::SocketEvents), } } impl ::prost::Name for SocketStreamedTraceSegment { diff --git a/src/generated/envoy.data.tap.v3.serde.rs b/src/generated/envoy.data.tap.v3.serde.rs index 8a6dfd9..b432871 100644 --- a/src/generated/envoy.data.tap.v3.serde.rs +++ b/src/generated/envoy.data.tap.v3.serde.rs @@ -871,6 +871,9 @@ impl serde::Serialize for SocketEvent { if self.timestamp.is_some() { len += 1; } + if self.connection.is_some() { + len += 1; + } if self.event_selector.is_some() { len += 1; } @@ -878,6 +881,9 @@ impl serde::Serialize for SocketEvent { if let Some(v) = self.timestamp.as_ref() { struct_ser.serialize_field("timestamp", v)?; } + if let Some(v) = self.connection.as_ref() { + struct_ser.serialize_field("connection", v)?; + } if let Some(v) = self.event_selector.as_ref() { match v { socket_event::EventSelector::Read(v) => { @@ -902,6 +908,7 @@ impl<'de> serde::Deserialize<'de> for SocketEvent { { const FIELDS: &[&str] = &[ "timestamp", + "connection", "read", "write", "closed", @@ -910,6 +917,7 @@ impl<'de> serde::Deserialize<'de> for SocketEvent { #[allow(clippy::enum_variant_names)] enum GeneratedField { Timestamp, + Connection, Read, Write, Closed, @@ -935,6 +943,7 @@ impl<'de> serde::Deserialize<'de> for SocketEvent { { match value { "timestamp" => Ok(GeneratedField::Timestamp), + "connection" => Ok(GeneratedField::Connection), "read" => Ok(GeneratedField::Read), "write" => Ok(GeneratedField::Write), "closed" => Ok(GeneratedField::Closed), @@ -958,6 +967,7 @@ impl<'de> serde::Deserialize<'de> for SocketEvent { V: serde::de::MapAccess<'de>, { let mut timestamp__ = None; + let mut connection__ = None; let mut event_selector__ = None; while let Some(k) = map_.next_key()? { match k { @@ -967,6 +977,12 @@ impl<'de> serde::Deserialize<'de> for SocketEvent { } timestamp__ = map_.next_value()?; } + GeneratedField::Connection => { + if connection__.is_some() { + return Err(serde::de::Error::duplicate_field("connection")); + } + connection__ = map_.next_value()?; + } GeneratedField::Read => { if event_selector__.is_some() { return Err(serde::de::Error::duplicate_field("read")); @@ -992,6 +1008,7 @@ impl<'de> serde::Deserialize<'de> for SocketEvent { } Ok(SocketEvent { timestamp: timestamp__, + connection: connection__, event_selector: event_selector__, }) } @@ -1270,6 +1287,97 @@ impl<'de> serde::Deserialize<'de> for socket_event::Write { deserializer.deserialize_struct("envoy.data.tap.v3.SocketEvent.Write", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for SocketEvents { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.events.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.data.tap.v3.SocketEvents", len)?; + if !self.events.is_empty() { + struct_ser.serialize_field("events", &self.events)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for SocketEvents { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "events", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Events, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "events" => Ok(GeneratedField::Events), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = SocketEvents; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.data.tap.v3.SocketEvents") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut events__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Events => { + if events__.is_some() { + return Err(serde::de::Error::duplicate_field("events")); + } + events__ = Some(map_.next_value()?); + } + } + } + Ok(SocketEvents { + events: events__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.data.tap.v3.SocketEvents", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for SocketStreamedTraceSegment { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -1298,6 +1406,9 @@ impl serde::Serialize for SocketStreamedTraceSegment { socket_streamed_trace_segment::MessagePiece::Event(v) => { struct_ser.serialize_field("event", v)?; } + socket_streamed_trace_segment::MessagePiece::Events(v) => { + struct_ser.serialize_field("events", v)?; + } } } struct_ser.end() @@ -1314,6 +1425,7 @@ impl<'de> serde::Deserialize<'de> for SocketStreamedTraceSegment { "traceId", "connection", "event", + "events", ]; #[allow(clippy::enum_variant_names)] @@ -1321,6 +1433,7 @@ impl<'de> serde::Deserialize<'de> for SocketStreamedTraceSegment { TraceId, Connection, Event, + Events, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -1345,6 +1458,7 @@ impl<'de> serde::Deserialize<'de> for SocketStreamedTraceSegment { "traceId" | "trace_id" => Ok(GeneratedField::TraceId), "connection" => Ok(GeneratedField::Connection), "event" => Ok(GeneratedField::Event), + "events" => Ok(GeneratedField::Events), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -1388,6 +1502,13 @@ impl<'de> serde::Deserialize<'de> for SocketStreamedTraceSegment { return Err(serde::de::Error::duplicate_field("event")); } message_piece__ = map_.next_value::<::std::option::Option<_>>()?.map(socket_streamed_trace_segment::MessagePiece::Event) +; + } + GeneratedField::Events => { + if message_piece__.is_some() { + return Err(serde::de::Error::duplicate_field("events")); + } + message_piece__ = map_.next_value::<::std::option::Option<_>>()?.map(socket_streamed_trace_segment::MessagePiece::Events) ; } } diff --git a/src/generated/envoy.extensions.clusters.aggregate.v3.rs b/src/generated/envoy.extensions.clusters.aggregate.v3.rs index 9a985e1..c17e3f9 100644 --- a/src/generated/envoy.extensions.clusters.aggregate.v3.rs +++ b/src/generated/envoy.extensions.clusters.aggregate.v3.rs @@ -19,3 +19,32 @@ impl ::prost::Name for ClusterConfig { "type.googleapis.com/envoy.extensions.clusters.aggregate.v3.ClusterConfig".into() } } +/// Configures an aggregate cluster whose +/// :ref:`ClusterConfig ` +/// is to be fetched from a separate xDS resource. +/// \[#extension: envoy.clusters.aggregate_resource\] +/// \[#not-implemented-hide:\] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AggregateClusterResource { + /// Configuration source specifier for the ClusterConfig resource. + /// Only the aggregated protocol variants are supported; if configured + /// otherwise, the cluster resource will be NACKed. + #[prost(message, optional, tag = "1")] + pub config_source: ::core::option::Option< + super::super::super::super::config::core::v3::ConfigSource, + >, + /// The name of the ClusterConfig resource to subscribe to. + #[prost(string, tag = "2")] + pub resource_name: ::prost::alloc::string::String, +} +impl ::prost::Name for AggregateClusterResource { + const NAME: &'static str = "AggregateClusterResource"; + const PACKAGE: &'static str = "envoy.extensions.clusters.aggregate.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.extensions.clusters.aggregate.v3.AggregateClusterResource".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.extensions.clusters.aggregate.v3.AggregateClusterResource" + .into() + } +} diff --git a/src/generated/envoy.extensions.clusters.aggregate.v3.serde.rs b/src/generated/envoy.extensions.clusters.aggregate.v3.serde.rs index 876e1ed..8ecda74 100644 --- a/src/generated/envoy.extensions.clusters.aggregate.v3.serde.rs +++ b/src/generated/envoy.extensions.clusters.aggregate.v3.serde.rs @@ -1,3 +1,113 @@ +impl serde::Serialize for AggregateClusterResource { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.config_source.is_some() { + len += 1; + } + if !self.resource_name.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.extensions.clusters.aggregate.v3.AggregateClusterResource", len)?; + if let Some(v) = self.config_source.as_ref() { + struct_ser.serialize_field("config_source", v)?; + } + if !self.resource_name.is_empty() { + struct_ser.serialize_field("resource_name", &self.resource_name)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for AggregateClusterResource { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "config_source", + "configSource", + "resource_name", + "resourceName", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ConfigSource, + ResourceName, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "configSource" | "config_source" => Ok(GeneratedField::ConfigSource), + "resourceName" | "resource_name" => Ok(GeneratedField::ResourceName), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = AggregateClusterResource; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.extensions.clusters.aggregate.v3.AggregateClusterResource") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut config_source__ = None; + let mut resource_name__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ConfigSource => { + if config_source__.is_some() { + return Err(serde::de::Error::duplicate_field("configSource")); + } + config_source__ = map_.next_value()?; + } + GeneratedField::ResourceName => { + if resource_name__.is_some() { + return Err(serde::de::Error::duplicate_field("resourceName")); + } + resource_name__ = Some(map_.next_value()?); + } + } + } + Ok(AggregateClusterResource { + config_source: config_source__, + resource_name: resource_name__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.extensions.clusters.aggregate.v3.AggregateClusterResource", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for ClusterConfig { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/src/generated/envoy.extensions.common.ratelimit.v3.rs b/src/generated/envoy.extensions.common.ratelimit.v3.rs index cfd7f28..1792eb6 100644 --- a/src/generated/envoy.extensions.common.ratelimit.v3.rs +++ b/src/generated/envoy.extensions.common.ratelimit.v3.rs @@ -52,6 +52,12 @@ pub struct RateLimitDescriptor { /// Optional rate limit override to supply to the ratelimit service. #[prost(message, optional, tag = "2")] pub limit: ::core::option::Option, + /// Optional hits_addend for the rate limit descriptor. If set the value will override the + /// request level hits_addend. + #[prost(message, optional, tag = "3")] + pub hits_addend: ::core::option::Option< + super::super::super::super::super::google::protobuf::UInt64Value, + >, } /// Nested message and enum types in `RateLimitDescriptor`. pub mod rate_limit_descriptor { @@ -60,7 +66,9 @@ pub mod rate_limit_descriptor { /// Descriptor key. #[prost(string, tag = "1")] pub key: ::prost::alloc::string::String, - /// Descriptor value. + /// Descriptor value. Blank value is treated as wildcard to create dynamic token buckets for each unique value. + /// Blank Values as wild card is currently supported only with envoy server instance level HTTP local rate limiting + /// and will not work if HTTP local rate limiting is enabled per connection level. #[prost(string, tag = "2")] pub value: ::prost::alloc::string::String, } @@ -114,6 +122,13 @@ impl ::prost::Name for RateLimitDescriptor { .into() } } +/// Configuration used to enable local rate limiting. +/// +/// .. note:: +/// The ``LocalRateLimitDescriptor`` is used to configure a local rate limit rule with a token +/// bucket algorithm. The ``RateLimitDescriptor`` is used to represent a list of symbols that +/// are used to match against the rate limit rule. +/// #[derive(Clone, PartialEq, ::prost::Message)] pub struct LocalRateLimitDescriptor { /// Descriptor entries. @@ -136,6 +151,28 @@ impl ::prost::Name for LocalRateLimitDescriptor { .into() } } +/// Configuration used to enable local cluster level rate limiting where the token buckets +/// will be shared across all the Envoy instances in the local cluster. +/// A share will be calculated based on the membership of the local cluster dynamically +/// and the configuration. When the limiter refilling the token bucket, the share will be +/// applied. By default, the token bucket will be shared evenly. +/// +/// See :ref:`local cluster name +/// ` for more context +/// about local cluster. +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct LocalClusterRateLimit {} +impl ::prost::Name for LocalClusterRateLimit { + const NAME: &'static str = "LocalClusterRateLimit"; + const PACKAGE: &'static str = "envoy.extensions.common.ratelimit.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.extensions.common.ratelimit.v3.LocalClusterRateLimit".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.extensions.common.ratelimit.v3.LocalClusterRateLimit" + .into() + } +} /// Defines the version of the standard to use for X-RateLimit headers. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] diff --git a/src/generated/envoy.extensions.common.ratelimit.v3.serde.rs b/src/generated/envoy.extensions.common.ratelimit.v3.serde.rs index f356269..9aa28dd 100644 --- a/src/generated/envoy.extensions.common.ratelimit.v3.serde.rs +++ b/src/generated/envoy.extensions.common.ratelimit.v3.serde.rs @@ -1,3 +1,74 @@ +impl serde::Serialize for LocalClusterRateLimit { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let len = 0; + let struct_ser = serializer.serialize_struct("envoy.extensions.common.ratelimit.v3.LocalClusterRateLimit", len)?; + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for LocalClusterRateLimit { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + Err(serde::de::Error::unknown_field(value, FIELDS)) + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = LocalClusterRateLimit; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.extensions.common.ratelimit.v3.LocalClusterRateLimit") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + while map_.next_key::()?.is_some() { + let _ = map_.next_value::()?; + } + Ok(LocalClusterRateLimit { + }) + } + } + deserializer.deserialize_struct("envoy.extensions.common.ratelimit.v3.LocalClusterRateLimit", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for LocalRateLimitDescriptor { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -121,6 +192,9 @@ impl serde::Serialize for RateLimitDescriptor { if self.limit.is_some() { len += 1; } + if self.hits_addend.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.extensions.common.ratelimit.v3.RateLimitDescriptor", len)?; if !self.entries.is_empty() { struct_ser.serialize_field("entries", &self.entries)?; @@ -128,6 +202,9 @@ impl serde::Serialize for RateLimitDescriptor { if let Some(v) = self.limit.as_ref() { struct_ser.serialize_field("limit", v)?; } + if let Some(v) = self.hits_addend.as_ref() { + struct_ser.serialize_field("hits_addend", v)?; + } struct_ser.end() } } @@ -140,12 +217,15 @@ impl<'de> serde::Deserialize<'de> for RateLimitDescriptor { const FIELDS: &[&str] = &[ "entries", "limit", + "hits_addend", + "hitsAddend", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { Entries, Limit, + HitsAddend, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -169,6 +249,7 @@ impl<'de> serde::Deserialize<'de> for RateLimitDescriptor { match value { "entries" => Ok(GeneratedField::Entries), "limit" => Ok(GeneratedField::Limit), + "hitsAddend" | "hits_addend" => Ok(GeneratedField::HitsAddend), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -190,6 +271,7 @@ impl<'de> serde::Deserialize<'de> for RateLimitDescriptor { { let mut entries__ = None; let mut limit__ = None; + let mut hits_addend__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Entries => { @@ -204,11 +286,18 @@ impl<'de> serde::Deserialize<'de> for RateLimitDescriptor { } limit__ = map_.next_value()?; } + GeneratedField::HitsAddend => { + if hits_addend__.is_some() { + return Err(serde::de::Error::duplicate_field("hitsAddend")); + } + hits_addend__ = map_.next_value()?; + } } } Ok(RateLimitDescriptor { entries: entries__.unwrap_or_default(), limit: limit__, + hits_addend: hits_addend__, }) } } diff --git a/src/generated/envoy.extensions.filters.http.ext_proc.v3.rs b/src/generated/envoy.extensions.filters.http.ext_proc.v3.rs index ce326b4..4ee6291 100644 --- a/src/generated/envoy.extensions.filters.http.ext_proc.v3.rs +++ b/src/generated/envoy.extensions.filters.http.ext_proc.v3.rs @@ -3,6 +3,9 @@ #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct ProcessingMode { /// How to handle the request header. Default is "SEND". + /// Note this field is ignored in :ref:`mode_override + /// `, since mode + /// overrides can only affect messages exchanged after the request header is processed. #[prost(enumeration = "processing_mode::HeaderSendMode", tag = "1")] pub request_header_mode: i32, /// How to handle the response header. Default is "SEND". @@ -37,9 +40,18 @@ pub mod processing_mode { )] #[repr(i32)] pub enum HeaderSendMode { - /// The default HeaderSendMode depends on which part of the message is being - /// processed. By default, request and response headers are sent, - /// while trailers are skipped. + /// When used to configure the ext_proc filter :ref:`processing_mode + /// `, + /// the default HeaderSendMode depends on which part of the message is being processed. By + /// default, request and response headers are sent, while trailers are skipped. + /// + /// When used in :ref:`mode_override + /// ` or + /// :ref:`allowed_override_modes + /// `, + /// a value of DEFAULT indicates that there is no change from the behavior that is configured for + /// the filter in :ref:`processing_mode + /// `. Default = 0, /// Send the header or trailer. Send = 1, @@ -70,11 +82,12 @@ pub mod processing_mode { } /// Control how the request and response bodies are handled /// When body mutation by external processor is enabled, ext_proc filter will always remove - /// the content length header in three cases below because content length can not be guaranteed + /// the content length header in four cases below because content length can not be guaranteed /// to be set correctly: /// 1) STREAMED BodySendMode: header processing completes before body mutation comes back. /// 2) BUFFERED_PARTIAL BodySendMode: body is buffered and could be injected in different phases. /// 3) BUFFERED BodySendMode + SKIP HeaderSendMode: header processing (e.g., update content-length) is skipped. + /// 4) FULL_DUPLEX_STREAMED BodySendMode: header processing completes before body mutation comes back. /// /// In Envoy's http1 codec implementation, removing content length will enable chunked transfer /// encoding whenever feasible. The recipient (either client or server) must be able @@ -111,6 +124,7 @@ pub mod processing_mode { /// chunk. If the body exceeds the configured buffer limit, then the body contents /// up to the buffer limit will be sent. BufferedPartial = 3, + FullDuplexStreamed = 4, } impl BodySendMode { /// String value of the enum field names used in the ProtoBuf definition. @@ -123,6 +137,7 @@ pub mod processing_mode { Self::Streamed => "STREAMED", Self::Buffered => "BUFFERED", Self::BufferedPartial => "BUFFERED_PARTIAL", + Self::FullDuplexStreamed => "FULL_DUPLEX_STREAMED", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -132,6 +147,7 @@ pub mod processing_mode { "STREAMED" => Some(Self::Streamed), "BUFFERED" => Some(Self::Buffered), "BUFFERED_PARTIAL" => Some(Self::BufferedPartial), + "FULL_DUPLEX_STREAMED" => Some(Self::FullDuplexStreamed), _ => None, } } diff --git a/src/generated/envoy.extensions.filters.http.ext_proc.v3.serde.rs b/src/generated/envoy.extensions.filters.http.ext_proc.v3.serde.rs index 98cbae1..0711a46 100644 --- a/src/generated/envoy.extensions.filters.http.ext_proc.v3.serde.rs +++ b/src/generated/envoy.extensions.filters.http.ext_proc.v3.serde.rs @@ -203,6 +203,7 @@ impl serde::Serialize for processing_mode::BodySendMode { Self::Streamed => "STREAMED", Self::Buffered => "BUFFERED", Self::BufferedPartial => "BUFFERED_PARTIAL", + Self::FullDuplexStreamed => "FULL_DUPLEX_STREAMED", }; serializer.serialize_str(variant) } @@ -218,6 +219,7 @@ impl<'de> serde::Deserialize<'de> for processing_mode::BodySendMode { "STREAMED", "BUFFERED", "BUFFERED_PARTIAL", + "FULL_DUPLEX_STREAMED", ]; struct GeneratedVisitor; @@ -262,6 +264,7 @@ impl<'de> serde::Deserialize<'de> for processing_mode::BodySendMode { "STREAMED" => Ok(processing_mode::BodySendMode::Streamed), "BUFFERED" => Ok(processing_mode::BodySendMode::Buffered), "BUFFERED_PARTIAL" => Ok(processing_mode::BodySendMode::BufferedPartial), + "FULL_DUPLEX_STREAMED" => Ok(processing_mode::BodySendMode::FullDuplexStreamed), _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), } } diff --git a/src/generated/envoy.extensions.filters.http.router.v3.rs b/src/generated/envoy.extensions.filters.http.router.v3.rs index 7c48290..40387c6 100644 --- a/src/generated/envoy.extensions.filters.http.router.v3.rs +++ b/src/generated/envoy.extensions.filters.http.router.v3.rs @@ -70,11 +70,11 @@ pub struct Router { /// for more details. #[prost(bool, tag = "7")] pub suppress_grpc_request_failure_code_stats: bool, + /// Optional HTTP filters for the upstream HTTP filter chain. + /// /// .. note:: /// Upstream HTTP filters are currently in alpha. /// - /// Optional HTTP filters for the upstream HTTP filter chain. - /// /// These filters will be applied for all requests that pass through the router. /// They will also be applied to shadowed requests. /// Upstream HTTP filters cannot change route or cluster. diff --git a/src/generated/envoy.extensions.filters.network.http_connection_manager.v3.rs b/src/generated/envoy.extensions.filters.network.http_connection_manager.v3.rs index c5aa00c..7edace2 100644 --- a/src/generated/envoy.extensions.filters.network.http_connection_manager.v3.rs +++ b/src/generated/envoy.extensions.filters.network.http_connection_manager.v3.rs @@ -1,5 +1,5 @@ // This file is @generated by prost-build. -/// \[#next-free-field: 58\] +/// \[#next-free-field: 59\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct HttpConnectionManager { /// Supplies the type of codec that the connection manager should use. @@ -28,11 +28,26 @@ pub struct HttpConnectionManager { #[prost(message, optional, tag = "7")] pub tracing: ::core::option::Option, /// Additional settings for HTTP requests handled by the connection manager. These will be - /// applicable to both HTTP1 and HTTP2 requests. + /// applicable to both HTTP/1.1 and HTTP/2 requests. #[prost(message, optional, tag = "35")] pub common_http_protocol_options: ::core::option::Option< super::super::super::super::super::config::core::v3::HttpProtocolOptions, >, + /// If set to ``true``, Envoy will not initiate an immediate drain timer for downstream HTTP/1 connections + /// once :ref:`common_http_protocol_options.max_connection_duration + /// ` is exceeded. + /// Instead, Envoy will wait until the next downstream request arrives, add a ``connection: close`` header + /// to the response, and then gracefully close the connection once the stream has completed. + /// + /// This behavior adheres to `RFC 9112, Section 9.6 <`_.> + /// + /// If set to ``false``, exceeding ``max_connection_duration`` triggers Envoy's default drain behavior for HTTP/1, + /// where the connection is eventually closed after all active streams finish. + /// + /// This option has no effect if ``max_connection_duration`` is not configured. + /// Defaults to ``false``. + #[prost(bool, tag = "58")] + pub http1_safe_max_connection_duration: bool, /// Additional HTTP/1 settings that are passed to the HTTP/1 codec. /// [#comment:TODO: The following fields are ignored when the /// :ref:`header validation configuration ` @@ -48,7 +63,6 @@ pub struct HttpConnectionManager { super::super::super::super::super::config::core::v3::Http2ProtocolOptions, >, /// Additional HTTP/3 settings that are passed directly to the HTTP/3 codec. - /// \[#not-implemented-hide:\] #[prost(message, optional, tag = "44")] pub http3_protocol_options: ::core::option::Option< super::super::super::super::super::config::core::v3::Http3ProtocolOptions, @@ -74,7 +88,16 @@ pub struct HttpConnectionManager { >, /// The maximum request headers size for incoming connections. /// If unconfigured, the default max request headers allowed is 60 KiB. + /// The default value can be overridden by setting runtime key ``envoy.reloadable_features.max_request_headers_size_kb``. /// Requests that exceed this limit will receive a 431 response. + /// + /// .. note:: + /// + /// Currently some protocol codecs impose limits on the maximum size of a single header. + /// + /// * HTTP/2 (when using nghttp2) limits a single header to around 100kb. + /// * HTTP/3 limits a single header to around 1024kb. + /// #[prost(message, optional, tag = "29")] pub max_request_headers_kb: ::core::option::Option< super::super::super::super::super::super::google::protobuf::UInt32Value, @@ -143,9 +166,10 @@ pub struct HttpConnectionManager { /// race with the final GOAWAY frame. During this grace period, Envoy will /// continue to accept new streams. After the grace period, a final GOAWAY /// frame is sent and Envoy will start refusing new streams. Draining occurs - /// both when a connection hits the idle timeout or during general server - /// draining. The default grace period is 5000 milliseconds (5 seconds) if this - /// option is not specified. + /// either when a connection hits the idle timeout, when :ref:`max_connection_duration + /// ` + /// is reached, or during general server draining. The default grace period is + /// 5000 milliseconds (5 seconds) if this option is not specified. #[prost(message, optional, tag = "12")] pub drain_timeout: ::core::option::Option< super::super::super::super::super::super::google::protobuf::Duration, @@ -155,31 +179,34 @@ pub struct HttpConnectionManager { /// during which Envoy will wait for the peer to close (i.e., a TCP FIN/RST is received by Envoy /// from the downstream connection) prior to Envoy closing the socket associated with that /// connection. - /// NOTE: This timeout is enforced even when the socket associated with the downstream connection - /// is pending a flush of the write buffer. However, any progress made writing data to the socket - /// will restart the timer associated with this timeout. This means that the total grace period for - /// a socket in this state will be - /// +. + /// + /// .. note:: + /// + /// This timeout is enforced even when the socket associated with the downstream connection is pending a flush of + /// the write buffer. However, any progress made writing data to the socket will restart the timer associated with + /// this timeout. This means that the total grace period for a socket in this state will be + /// +. /// /// Delaying Envoy's connection close and giving the peer the opportunity to initiate the close /// sequence mitigates a race condition that exists when downstream clients do not drain/process /// data in a connection's receive buffer after a remote close has been detected via a socket - /// write(). This race leads to such clients failing to process the response code sent by Envoy, + /// ``write()``. This race leads to such clients failing to process the response code sent by Envoy, /// which could result in erroneous downstream processing. /// /// If the timeout triggers, Envoy will close the connection's socket. /// /// The default timeout is 1000 ms if this option is not specified. /// - /// .. NOTE:: + /// .. note:: /// To be useful in avoiding the race condition described above, this timeout must be set /// to *at least* +<100ms to account for /// a reasonable "worst" case processing time for a full iteration of Envoy's event loop>. /// - /// .. WARNING:: - /// A value of 0 will completely disable delayed close processing. When disabled, the downstream + /// .. warning:: + /// A value of ``0`` will completely disable delayed close processing. When disabled, the downstream /// connection's socket will be closed immediately after the write flush is completed or will /// never close if the write flush does not complete. + /// #[prost(message, optional, tag = "26")] pub delayed_close_timeout: ::core::option::Option< super::super::super::super::super::super::google::protobuf::Duration, @@ -190,25 +217,32 @@ pub struct HttpConnectionManager { pub access_log: ::prost::alloc::vec::Vec< super::super::super::super::super::config::accesslog::v3::AccessLog, >, + /// The interval to flush the above access logs. + /// /// .. attention:: - /// This field is deprecated in favor of - /// :ref:`access_log_flush_interval - /// `. - /// Note that if both this field and :ref:`access_log_flush_interval - /// ` - /// are specified, the former (deprecated field) is ignored. + /// + /// This field is deprecated in favor of + /// :ref:`access_log_flush_interval + /// `. + /// Note that if both this field and :ref:`access_log_flush_interval + /// ` + /// are specified, the former (deprecated field) is ignored. #[deprecated] #[prost(message, optional, tag = "54")] pub access_log_flush_interval: ::core::option::Option< super::super::super::super::super::super::google::protobuf::Duration, >, + /// If set to true, HCM will flush an access log once when a new HTTP request is received, after the request + /// headers have been evaluated, and before iterating through the HTTP filter chain. + /// /// .. attention:: - /// This field is deprecated in favor of - /// :ref:`flush_access_log_on_new_request - /// `. - /// Note that if both this field and :ref:`flush_access_log_on_new_request - /// ` - /// are specified, the former (deprecated field) is ignored. + /// + /// This field is deprecated in favor of + /// :ref:`flush_access_log_on_new_request + /// `. + /// Note that if both this field and :ref:`flush_access_log_on_new_request + /// ` + /// are specified, the former (deprecated field) is ignored. #[deprecated] #[prost(bool, tag = "55")] pub flush_access_log_on_new_request: bool, @@ -235,20 +269,19 @@ pub struct HttpConnectionManager { /// :ref:`config_http_conn_man_headers_x-forwarded-for` for more information. #[prost(uint32, tag = "19")] pub xff_num_trusted_hops: u32, - /// The configuration for the original IP detection extensions. - /// - /// When configured the extensions will be called along with the request headers - /// and information about the downstream connection, such as the directly connected address. - /// Each extension will then use these parameters to decide the request's effective remote address. - /// If an extension fails to detect the original IP address and isn't configured to reject - /// the request, the HCM will try the remaining extensions until one succeeds or rejects - /// the request. If the request isn't rejected nor any extension succeeds, the HCM will - /// fallback to using the remote address. - /// - /// .. WARNING:: - /// Extensions cannot be used in conjunction with :ref:`use_remote_address + /// Configuration for original IP detection extensions. + /// + /// When these extensions are configured, Envoy will invoke them with the incoming request headers and + /// details about the downstream connection, including the directly connected address. Each extension uses + /// this information to determine the effective remote IP address for the request. If an extension cannot + /// identify the original IP address and isn't set to reject the request, Envoy will sequentially attempt + /// the remaining extensions until one successfully determines the IP or explicitly rejects the request. + /// If all extensions fail without rejection, Envoy defaults to using the directly connected remote address. + /// + /// .. warning:: + /// These extensions cannot be configured simultaneously with :ref:`use_remote_address /// ` - /// nor :ref:`xff_num_trusted_hops + /// or :ref:`xff_num_trusted_hops /// `. /// /// \[#extension-category: envoy.http.original_ip_detection\] @@ -271,6 +304,34 @@ pub struct HttpConnectionManager { /// purposes. If unspecified, only RFC1918 IP addresses will be considered internal. /// See the documentation for :ref:`config_http_conn_man_headers_x-envoy-internal` for more /// information about internal/external addresses. + /// + /// .. warning:: + /// As of Envoy 1.33.0 no IP addresses will be considered trusted. If you have tooling such as probes + /// on your private network which need to be treated as trusted (e.g. changing arbitrary x-envoy headers) + /// you will have to manually include those addresses or CIDR ranges like: + /// + /// .. validated-code-block:: yaml + /// :type-name: envoy.extensions.filters.network.http_connection_manager.v3.InternalAddressConfig + /// + /// cidr_ranges: + /// address_prefix: 10.0.0.0 + /// prefix_len: 8 + /// cidr_ranges: + /// address_prefix: 192.168.0.0 + /// prefix_len: 16 + /// cidr_ranges: + /// address_prefix: 172.16.0.0 + /// prefix_len: 12 + /// cidr_ranges: + /// address_prefix: 127.0.0.1 + /// prefix_len: 32 + /// cidr_ranges: + /// address_prefix: fd00:: + /// prefix_len: 8 + /// cidr_ranges: + /// address_prefix: ::1 + /// prefix_len: 128 + /// #[prost(message, optional, tag = "25")] pub internal_address_config: ::core::option::Option< http_connection_manager::InternalAddressConfig, @@ -575,14 +636,6 @@ pub mod http_connection_manager { >, /// Configuration for an external tracing provider. /// If not specified, no tracing will be performed. - /// - /// .. attention:: - /// Please be aware that ``envoy.tracers.opencensus`` provider can only be configured once - /// in Envoy lifetime. - /// Any attempts to reconfigure it or to use different configurations for different HCM filters - /// will be rejected. - /// Such a constraint is inherent to OpenCensus itself. It cannot be overcome without changes - /// on OpenCensus side. #[prost(message, optional, tag = "9")] pub provider: ::core::option::Option< super::super::super::super::super::super::config::trace::v3::tracing::Http, @@ -733,13 +786,12 @@ pub mod http_connection_manager { /// /// .. warning:: /// - /// The current implementation of upgrade headers does not handle - /// multi-valued upgrade headers. Support for multi-valued headers may be - /// added in the future if needed. + /// The current implementation of upgrade headers does not handle multi-valued upgrade headers. Support for + /// multi-valued headers may be added in the future if needed. /// /// .. warning:: - /// The current implementation of upgrade headers does not work with HTTP/2 - /// upstreams. + /// The current implementation of upgrade headers does not work with HTTP/2 upstreams. + /// #[derive(Clone, PartialEq, ::prost::Message)] pub struct UpgradeConfig { /// The case-insensitive name of this upgrade, e.g. "websocket". @@ -782,7 +834,10 @@ pub mod http_connection_manager { /// `) will apply to the ``:path`` header /// destined for the upstream. /// - /// Note: access logging and tracing will show the original ``:path`` header. + /// .. note:: + /// + /// Access logging and tracing will show the original ``:path`` header. + /// #[derive(Clone, PartialEq, ::prost::Message)] pub struct PathNormalizationOptions { /// \[#not-implemented-hide:\] Normalization applies internally before any processing of requests by @@ -957,9 +1012,8 @@ pub mod http_connection_manager { /// (Envoy does not require HTTP/2 to take place over TLS or to use ALPN. /// Prior knowledge is allowed). Http2 = 2, - /// \[#not-implemented-hide:\] QUIC implementation is not production ready yet. Use this enum with - /// caution to prevent accidental execution of QUIC code. I.e. `!= HTTP2` is no longer sufficient - /// to distinguish HTTP1 and HTTP2 traffic. + /// The connection manager will assume that the client is speaking HTTP/3. + /// This needs to be consistent with listener and transport socket config. Http3 = 3, } impl CodecType { @@ -1086,7 +1140,7 @@ pub mod http_connection_manager { } } } - /// Determines the action for request that contain %2F, %2f, %5C or %5c sequences in the URI path. + /// Determines the action for request that contain ``%2F``, ``%2f``, ``%5C`` or ``%5c`` sequences in the URI path. /// This operation occurs before URL normalization and the merge slashes transformations if they were enabled. #[derive( Clone, @@ -1103,24 +1157,34 @@ pub mod http_connection_manager { pub enum PathWithEscapedSlashesAction { /// Default behavior specific to implementation (i.e. Envoy) of this configuration option. /// Envoy, by default, takes the KEEP_UNCHANGED action. - /// NOTE: the implementation may change the default behavior at-will. + /// + /// .. note:: + /// + /// The implementation may change the default behavior at-will. ImplementationSpecificDefault = 0, /// Keep escaped slashes. KeepUnchanged = 1, /// Reject client request with the 400 status. gRPC requests will be rejected with the INTERNAL (13) error code. - /// The "httpN.downstream_rq_failed_path_normalization" counter is incremented for each rejected request. + /// The ``httpN.downstream_rq_failed_path_normalization`` counter is incremented for each rejected request. RejectRequest = 2, - /// Unescape %2F and %5C sequences and redirect request to the new path if these sequences were present. + /// Unescape ``%2F`` and ``%5C`` sequences and redirect request to the new path if these sequences were present. /// Redirect occurs after path normalization and merge slashes transformations if they were configured. - /// NOTE: gRPC requests will be rejected with the INTERNAL (13) error code. - /// This option minimizes possibility of path confusion exploits by forcing request with unescaped slashes to - /// traverse all parties: downstream client, intermediate proxies, Envoy and upstream server. - /// The "httpN.downstream_rq_redirected_with_normalized_path" counter is incremented for each - /// redirected request. + /// + /// .. note:: + /// + /// gRPC requests will be rejected with the INTERNAL (13) error code. This option minimizes possibility of path + /// confusion exploits by forcing request with unescaped slashes to traverse all parties: downstream client, + /// intermediate proxies, Envoy and upstream server. The ``httpN.downstream_rq_redirected_with_normalized_path`` + /// counter is incremented for each redirected request. + /// UnescapeAndRedirect = 3, - /// Unescape %2F and %5C sequences. - /// Note: this option should not be enabled if intermediaries perform path based access control as - /// it may lead to path confusion vulnerabilities. + /// Unescape ``%2F`` and ``%5C`` sequences. + /// + /// .. note:: + /// + /// This option should not be enabled if intermediaries perform path based access control as it may lead to path + /// confusion vulnerabilities. + /// UnescapeAndForward = 4, } impl PathWithEscapedSlashesAction { diff --git a/src/generated/envoy.extensions.filters.network.http_connection_manager.v3.serde.rs b/src/generated/envoy.extensions.filters.network.http_connection_manager.v3.serde.rs index 64d3d58..63745a4 100644 --- a/src/generated/envoy.extensions.filters.network.http_connection_manager.v3.serde.rs +++ b/src/generated/envoy.extensions.filters.network.http_connection_manager.v3.serde.rs @@ -115,6 +115,9 @@ impl serde::Serialize for HttpConnectionManager { if self.common_http_protocol_options.is_some() { len += 1; } + if self.http1_safe_max_connection_duration { + len += 1; + } if self.http_protocol_options.is_some() { len += 1; } @@ -277,6 +280,9 @@ impl serde::Serialize for HttpConnectionManager { if let Some(v) = self.common_http_protocol_options.as_ref() { struct_ser.serialize_field("common_http_protocol_options", v)?; } + if self.http1_safe_max_connection_duration { + struct_ser.serialize_field("http1_safe_max_connection_duration", &self.http1_safe_max_connection_duration)?; + } if let Some(v) = self.http_protocol_options.as_ref() { struct_ser.serialize_field("http_protocol_options", v)?; } @@ -459,6 +465,8 @@ impl<'de> serde::Deserialize<'de> for HttpConnectionManager { "tracing", "common_http_protocol_options", "commonHttpProtocolOptions", + "http1_safe_max_connection_duration", + "http1SafeMaxConnectionDuration", "http_protocol_options", "httpProtocolOptions", "http2_protocol_options", @@ -565,6 +573,7 @@ impl<'de> serde::Deserialize<'de> for HttpConnectionManager { AddUserAgent, Tracing, CommonHttpProtocolOptions, + Http1SafeMaxConnectionDuration, HttpProtocolOptions, Http2ProtocolOptions, Http3ProtocolOptions, @@ -641,6 +650,7 @@ impl<'de> serde::Deserialize<'de> for HttpConnectionManager { "addUserAgent" | "add_user_agent" => Ok(GeneratedField::AddUserAgent), "tracing" => Ok(GeneratedField::Tracing), "commonHttpProtocolOptions" | "common_http_protocol_options" => Ok(GeneratedField::CommonHttpProtocolOptions), + "http1SafeMaxConnectionDuration" | "http1_safe_max_connection_duration" => Ok(GeneratedField::Http1SafeMaxConnectionDuration), "httpProtocolOptions" | "http_protocol_options" => Ok(GeneratedField::HttpProtocolOptions), "http2ProtocolOptions" | "http2_protocol_options" => Ok(GeneratedField::Http2ProtocolOptions), "http3ProtocolOptions" | "http3_protocol_options" => Ok(GeneratedField::Http3ProtocolOptions), @@ -715,6 +725,7 @@ impl<'de> serde::Deserialize<'de> for HttpConnectionManager { let mut add_user_agent__ = None; let mut tracing__ = None; let mut common_http_protocol_options__ = None; + let mut http1_safe_max_connection_duration__ = None; let mut http_protocol_options__ = None; let mut http2_protocol_options__ = None; let mut http3_protocol_options__ = None; @@ -800,6 +811,12 @@ impl<'de> serde::Deserialize<'de> for HttpConnectionManager { } common_http_protocol_options__ = map_.next_value()?; } + GeneratedField::Http1SafeMaxConnectionDuration => { + if http1_safe_max_connection_duration__.is_some() { + return Err(serde::de::Error::duplicate_field("http1SafeMaxConnectionDuration")); + } + http1_safe_max_connection_duration__ = Some(map_.next_value()?); + } GeneratedField::HttpProtocolOptions => { if http_protocol_options__.is_some() { return Err(serde::de::Error::duplicate_field("httpProtocolOptions")); @@ -1108,6 +1125,7 @@ impl<'de> serde::Deserialize<'de> for HttpConnectionManager { add_user_agent: add_user_agent__, tracing: tracing__, common_http_protocol_options: common_http_protocol_options__, + http1_safe_max_connection_duration: http1_safe_max_connection_duration__.unwrap_or_default(), http_protocol_options: http_protocol_options__, http2_protocol_options: http2_protocol_options__, http3_protocol_options: http3_protocol_options__, diff --git a/src/generated/envoy.extensions.transport_sockets.tls.v3.rs b/src/generated/envoy.extensions.transport_sockets.tls.v3.rs index d909ef0..f090231 100644 --- a/src/generated/envoy.extensions.transport_sockets.tls.v3.rs +++ b/src/generated/envoy.extensions.transport_sockets.tls.v3.rs @@ -1,5 +1,5 @@ // This file is @generated by prost-build. -/// \[#next-free-field: 6\] +/// \[#next-free-field: 7\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct TlsParameters { /// Minimum TLS protocol version. By default, it's ``TLSv1_2`` for both clients and servers. @@ -115,6 +115,16 @@ pub struct TlsParameters { /// ecdsa_sha1 #[prost(string, repeated, tag = "5")] pub signature_algorithms: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// Compliance policies configure various aspects of the TLS based on the given policy. + /// The policies are applied last during configuration and may override the other TLS + /// parameters, or any previous policy. + #[prost( + enumeration = "tls_parameters::CompliancePolicy", + repeated, + packed = "false", + tag = "6" + )] + pub compliance_policies: ::prost::alloc::vec::Vec, } /// Nested message and enum types in `TlsParameters`. pub mod tls_parameters { @@ -168,6 +178,52 @@ pub mod tls_parameters { } } } + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum CompliancePolicy { + /// FIPS_202205 configures a TLS connection to use: + /// + /// * TLS 1.2 or 1.3 + /// * For TLS 1.2, only ECDHE_\[RSA|ECDSA\]_WITH_AES_*_GCM_SHA*. + /// * For TLS 1.3, only AES-GCM + /// * P-256 or P-384 for key agreement. + /// * For server signatures, only ``PKCS#1/PSS`` with ``SHA256/384/512``, or ECDSA + /// with P-256 or P-384. + /// + /// .. attention:: + /// + /// Please refer to `BoringSSL policies <`_> + /// for details. + Fips202205 = 0, + } + impl CompliancePolicy { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Fips202205 => "FIPS_202205", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "FIPS_202205" => Some(Self::Fips202205), + _ => None, + } + } + } } impl ::prost::Name for TlsParameters { const NAME: &'static str = "TlsParameters"; @@ -272,12 +328,13 @@ pub struct TlsCertificate { super::super::super::super::config::core::v3::WatchedDirectory, >, /// BoringSSL private key method provider. This is an alternative to :ref:`private_key - /// ` field. This can't be - /// marked as ``oneof`` due to API compatibility reasons. Setting both :ref:`private_key - /// ` and - /// :ref:`private_key_provider - /// ` fields will result in an - /// error. + /// ` field. + /// When both :ref:`private_key ` and + /// :ref:`private_key_provider ` fields are set, + /// ``private_key_provider`` takes precedence. + /// If ``private_key_provider`` is unavailable and :ref:`fallback + /// ` + /// is enabled, ``private_key`` will be used. #[prost(message, optional, tag = "6")] pub private_key_provider: ::core::option::Option, /// The password to decrypt the TLS private key. If this field is not set, it is assumed that the @@ -358,7 +415,7 @@ impl ::prost::Name for TlsSessionTicketKeys { /// \[#not-implemented-hide:\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct CertificateProviderPluginInstance { - /// Provider instance name. If not present, defaults to "default". + /// Provider instance name. /// /// Instance names should generally be defined not in terms of the underlying provider /// implementation (e.g., "file_watcher") but rather in terms of the function of the @@ -391,10 +448,32 @@ pub struct SubjectAltNameMatcher { #[prost(enumeration = "subject_alt_name_matcher::SanType", tag = "1")] pub san_type: i32, /// Matcher for SAN value. + /// + /// If the :ref:`san_type ` + /// is :ref:`DNS ` + /// and the matcher type is :ref:`exact `, DNS wildcards are evaluated + /// according to the rules in + /// For example, ``*.example.com`` would match ``test.example.com`` but not ``example.com`` and not + /// ``a.b.example.com``. + /// + /// The string matching for OTHER_NAME SAN values depends on their ASN.1 type: + /// + /// * OBJECT: Validated against its dotted numeric notation (e.g., "1.2.3.4") + /// * BOOLEAN: Validated against strings "true" or "false" + /// * INTEGER/ENUMERATED: Validated against a string containing the integer value + /// * NULL: Validated against an empty string + /// * Other types: Validated directly against the string value #[prost(message, optional, tag = "2")] pub matcher: ::core::option::Option< super::super::super::super::r#type::matcher::v3::StringMatcher, >, + /// OID Value which is required if OTHER_NAME SAN type is used. + /// For example, UPN OID is 1.3.6.1.4.1.311.20.2.3 + /// (Reference: ). + /// + /// If set for SAN types other than OTHER_NAME, it will be ignored. + #[prost(string, tag = "3")] + pub oid: ::prost::alloc::string::String, } /// Nested message and enum types in `SubjectAltNameMatcher`. pub mod subject_alt_name_matcher { @@ -418,6 +497,7 @@ pub mod subject_alt_name_matcher { Dns = 2, Uri = 3, IpAddress = 4, + OtherName = 5, } impl SanType { /// String value of the enum field names used in the ProtoBuf definition. @@ -431,6 +511,7 @@ pub mod subject_alt_name_matcher { Self::Dns => "DNS", Self::Uri => "URI", Self::IpAddress => "IP_ADDRESS", + Self::OtherName => "OTHER_NAME", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -441,6 +522,7 @@ pub mod subject_alt_name_matcher { "DNS" => Some(Self::Dns), "URI" => Some(Self::Uri), "IP_ADDRESS" => Some(Self::IpAddress), + "OTHER_NAME" => Some(Self::OtherName), _ => None, } } @@ -755,11 +837,19 @@ impl ::prost::Name for CertificateValidationContext { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct GenericSecret { - /// Secret of generic type and is available to filters. + /// Secret of generic type and is available to filters. It is expected + /// that only only one of secret and secrets is set. #[prost(message, optional, tag = "1")] pub secret: ::core::option::Option< super::super::super::super::config::core::v3::DataSource, >, + /// For cases where multiple associated secrets need to be distributed together. It is expected + /// that only only one of secret and secrets is set. + #[prost(map = "string, message", tag = "2")] + pub secrets: ::std::collections::HashMap< + ::prost::alloc::string::String, + super::super::super::super::config::core::v3::DataSource, + >, } impl ::prost::Name for GenericSecret { const NAME: &'static str = "GenericSecret"; diff --git a/src/generated/envoy.extensions.transport_sockets.tls.v3.serde.rs b/src/generated/envoy.extensions.transport_sockets.tls.v3.serde.rs index bb7b277..02ed574 100644 --- a/src/generated/envoy.extensions.transport_sockets.tls.v3.serde.rs +++ b/src/generated/envoy.extensions.transport_sockets.tls.v3.serde.rs @@ -606,10 +606,16 @@ impl serde::Serialize for GenericSecret { if self.secret.is_some() { len += 1; } + if !self.secrets.is_empty() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.extensions.transport_sockets.tls.v3.GenericSecret", len)?; if let Some(v) = self.secret.as_ref() { struct_ser.serialize_field("secret", v)?; } + if !self.secrets.is_empty() { + struct_ser.serialize_field("secrets", &self.secrets)?; + } struct_ser.end() } } @@ -621,11 +627,13 @@ impl<'de> serde::Deserialize<'de> for GenericSecret { { const FIELDS: &[&str] = &[ "secret", + "secrets", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { Secret, + Secrets, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -648,6 +656,7 @@ impl<'de> serde::Deserialize<'de> for GenericSecret { { match value { "secret" => Ok(GeneratedField::Secret), + "secrets" => Ok(GeneratedField::Secrets), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -668,6 +677,7 @@ impl<'de> serde::Deserialize<'de> for GenericSecret { V: serde::de::MapAccess<'de>, { let mut secret__ = None; + let mut secrets__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Secret => { @@ -676,10 +686,19 @@ impl<'de> serde::Deserialize<'de> for GenericSecret { } secret__ = map_.next_value()?; } + GeneratedField::Secrets => { + if secrets__.is_some() { + return Err(serde::de::Error::duplicate_field("secrets")); + } + secrets__ = Some( + map_.next_value::>()? + ); + } } } Ok(GenericSecret { secret: secret__, + secrets: secrets__.unwrap_or_default(), }) } } @@ -1097,6 +1116,9 @@ impl serde::Serialize for SubjectAltNameMatcher { if self.matcher.is_some() { len += 1; } + if !self.oid.is_empty() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.extensions.transport_sockets.tls.v3.SubjectAltNameMatcher", len)?; if self.san_type != 0 { let v = subject_alt_name_matcher::SanType::try_from(self.san_type) @@ -1106,6 +1128,9 @@ impl serde::Serialize for SubjectAltNameMatcher { if let Some(v) = self.matcher.as_ref() { struct_ser.serialize_field("matcher", v)?; } + if !self.oid.is_empty() { + struct_ser.serialize_field("oid", &self.oid)?; + } struct_ser.end() } } @@ -1119,12 +1144,14 @@ impl<'de> serde::Deserialize<'de> for SubjectAltNameMatcher { "san_type", "sanType", "matcher", + "oid", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { SanType, Matcher, + Oid, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -1148,6 +1175,7 @@ impl<'de> serde::Deserialize<'de> for SubjectAltNameMatcher { match value { "sanType" | "san_type" => Ok(GeneratedField::SanType), "matcher" => Ok(GeneratedField::Matcher), + "oid" => Ok(GeneratedField::Oid), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -1169,6 +1197,7 @@ impl<'de> serde::Deserialize<'de> for SubjectAltNameMatcher { { let mut san_type__ = None; let mut matcher__ = None; + let mut oid__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::SanType => { @@ -1183,11 +1212,18 @@ impl<'de> serde::Deserialize<'de> for SubjectAltNameMatcher { } matcher__ = map_.next_value()?; } + GeneratedField::Oid => { + if oid__.is_some() { + return Err(serde::de::Error::duplicate_field("oid")); + } + oid__ = Some(map_.next_value()?); + } } } Ok(SubjectAltNameMatcher { san_type: san_type__.unwrap_or_default(), matcher: matcher__, + oid: oid__.unwrap_or_default(), }) } } @@ -1206,6 +1242,7 @@ impl serde::Serialize for subject_alt_name_matcher::SanType { Self::Dns => "DNS", Self::Uri => "URI", Self::IpAddress => "IP_ADDRESS", + Self::OtherName => "OTHER_NAME", }; serializer.serialize_str(variant) } @@ -1222,6 +1259,7 @@ impl<'de> serde::Deserialize<'de> for subject_alt_name_matcher::SanType { "DNS", "URI", "IP_ADDRESS", + "OTHER_NAME", ]; struct GeneratedVisitor; @@ -1267,6 +1305,7 @@ impl<'de> serde::Deserialize<'de> for subject_alt_name_matcher::SanType { "DNS" => Ok(subject_alt_name_matcher::SanType::Dns), "URI" => Ok(subject_alt_name_matcher::SanType::Uri), "IP_ADDRESS" => Ok(subject_alt_name_matcher::SanType::IpAddress), + "OTHER_NAME" => Ok(subject_alt_name_matcher::SanType::OtherName), _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), } } @@ -1513,6 +1552,9 @@ impl serde::Serialize for TlsParameters { if !self.signature_algorithms.is_empty() { len += 1; } + if !self.compliance_policies.is_empty() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.extensions.transport_sockets.tls.v3.TlsParameters", len)?; if self.tls_minimum_protocol_version != 0 { let v = tls_parameters::TlsProtocol::try_from(self.tls_minimum_protocol_version) @@ -1533,6 +1575,13 @@ impl serde::Serialize for TlsParameters { if !self.signature_algorithms.is_empty() { struct_ser.serialize_field("signature_algorithms", &self.signature_algorithms)?; } + if !self.compliance_policies.is_empty() { + let v = self.compliance_policies.iter().cloned().map(|v| { + tls_parameters::CompliancePolicy::try_from(v) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", v))) + }).collect::, _>>()?; + struct_ser.serialize_field("compliance_policies", &v)?; + } struct_ser.end() } } @@ -1553,6 +1602,8 @@ impl<'de> serde::Deserialize<'de> for TlsParameters { "ecdhCurves", "signature_algorithms", "signatureAlgorithms", + "compliance_policies", + "compliancePolicies", ]; #[allow(clippy::enum_variant_names)] @@ -1562,6 +1613,7 @@ impl<'de> serde::Deserialize<'de> for TlsParameters { CipherSuites, EcdhCurves, SignatureAlgorithms, + CompliancePolicies, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -1588,6 +1640,7 @@ impl<'de> serde::Deserialize<'de> for TlsParameters { "cipherSuites" | "cipher_suites" => Ok(GeneratedField::CipherSuites), "ecdhCurves" | "ecdh_curves" => Ok(GeneratedField::EcdhCurves), "signatureAlgorithms" | "signature_algorithms" => Ok(GeneratedField::SignatureAlgorithms), + "compliancePolicies" | "compliance_policies" => Ok(GeneratedField::CompliancePolicies), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -1612,6 +1665,7 @@ impl<'de> serde::Deserialize<'de> for TlsParameters { let mut cipher_suites__ = None; let mut ecdh_curves__ = None; let mut signature_algorithms__ = None; + let mut compliance_policies__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::TlsMinimumProtocolVersion => { @@ -1644,6 +1698,12 @@ impl<'de> serde::Deserialize<'de> for TlsParameters { } signature_algorithms__ = Some(map_.next_value()?); } + GeneratedField::CompliancePolicies => { + if compliance_policies__.is_some() { + return Err(serde::de::Error::duplicate_field("compliancePolicies")); + } + compliance_policies__ = Some(map_.next_value::>()?.into_iter().map(|x| x as i32).collect()); + } } } Ok(TlsParameters { @@ -1652,12 +1712,81 @@ impl<'de> serde::Deserialize<'de> for TlsParameters { cipher_suites: cipher_suites__.unwrap_or_default(), ecdh_curves: ecdh_curves__.unwrap_or_default(), signature_algorithms: signature_algorithms__.unwrap_or_default(), + compliance_policies: compliance_policies__.unwrap_or_default(), }) } } deserializer.deserialize_struct("envoy.extensions.transport_sockets.tls.v3.TlsParameters", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for tls_parameters::CompliancePolicy { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + let variant = match self { + Self::Fips202205 => "FIPS_202205", + }; + serializer.serialize_str(variant) + } +} +impl<'de> serde::Deserialize<'de> for tls_parameters::CompliancePolicy { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "FIPS_202205", + ]; + + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = tls_parameters::CompliancePolicy; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + fn visit_i64(self, v: i64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) + }) + } + + fn visit_u64(self, v: u64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) + }) + } + + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "FIPS_202205" => Ok(tls_parameters::CompliancePolicy::Fips202205), + _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), + } + } + } + deserializer.deserialize_any(GeneratedVisitor) + } +} impl serde::Serialize for tls_parameters::TlsProtocol { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/src/generated/envoy.r#type.http.v3.rs b/src/generated/envoy.r#type.http.v3.rs index cd17089..b40a116 100644 --- a/src/generated/envoy.r#type.http.v3.rs +++ b/src/generated/envoy.r#type.http.v3.rs @@ -16,6 +16,9 @@ pub struct Cookie { /// If no path is specified here, no path will be set for the cookie. #[prost(string, tag = "3")] pub path: ::prost::alloc::string::String, + /// Additional attributes for the cookie. They will be used when generating a new cookie. + #[prost(message, repeated, tag = "4")] + pub attributes: ::prost::alloc::vec::Vec, } impl ::prost::Name for Cookie { const NAME: &'static str = "Cookie"; @@ -27,6 +30,26 @@ impl ::prost::Name for Cookie { "type.googleapis.com/envoy.type.http.v3.Cookie".into() } } +/// CookieAttribute defines an API for adding additional attributes for a HTTP cookie. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CookieAttribute { + /// The name of the cookie attribute. + #[prost(string, tag = "1")] + pub name: ::prost::alloc::string::String, + /// The optional value of the cookie attribute. + #[prost(string, tag = "2")] + pub value: ::prost::alloc::string::String, +} +impl ::prost::Name for CookieAttribute { + const NAME: &'static str = "CookieAttribute"; + const PACKAGE: &'static str = "envoy.type.http.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.type.http.v3.CookieAttribute".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.type.http.v3.CookieAttribute".into() + } +} #[derive(Clone, PartialEq, ::prost::Message)] pub struct PathTransformation { /// A list of operations to apply. Transformations will be performed in the order that they appear. diff --git a/src/generated/envoy.r#type.http.v3.serde.rs b/src/generated/envoy.r#type.http.v3.serde.rs index b35f074..e5182e4 100644 --- a/src/generated/envoy.r#type.http.v3.serde.rs +++ b/src/generated/envoy.r#type.http.v3.serde.rs @@ -15,6 +15,9 @@ impl serde::Serialize for Cookie { if !self.path.is_empty() { len += 1; } + if !self.attributes.is_empty() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.r#type.http.v3.Cookie", len)?; if !self.name.is_empty() { struct_ser.serialize_field("name", &self.name)?; @@ -25,6 +28,9 @@ impl serde::Serialize for Cookie { if !self.path.is_empty() { struct_ser.serialize_field("path", &self.path)?; } + if !self.attributes.is_empty() { + struct_ser.serialize_field("attributes", &self.attributes)?; + } struct_ser.end() } } @@ -38,6 +44,7 @@ impl<'de> serde::Deserialize<'de> for Cookie { "name", "ttl", "path", + "attributes", ]; #[allow(clippy::enum_variant_names)] @@ -45,6 +52,7 @@ impl<'de> serde::Deserialize<'de> for Cookie { Name, Ttl, Path, + Attributes, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -69,6 +77,7 @@ impl<'de> serde::Deserialize<'de> for Cookie { "name" => Ok(GeneratedField::Name), "ttl" => Ok(GeneratedField::Ttl), "path" => Ok(GeneratedField::Path), + "attributes" => Ok(GeneratedField::Attributes), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -91,6 +100,7 @@ impl<'de> serde::Deserialize<'de> for Cookie { let mut name__ = None; let mut ttl__ = None; let mut path__ = None; + let mut attributes__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Name => { @@ -111,18 +121,133 @@ impl<'de> serde::Deserialize<'de> for Cookie { } path__ = Some(map_.next_value()?); } + GeneratedField::Attributes => { + if attributes__.is_some() { + return Err(serde::de::Error::duplicate_field("attributes")); + } + attributes__ = Some(map_.next_value()?); + } } } Ok(Cookie { name: name__.unwrap_or_default(), ttl: ttl__, path: path__.unwrap_or_default(), + attributes: attributes__.unwrap_or_default(), }) } } deserializer.deserialize_struct("envoy.r#type.http.v3.Cookie", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for CookieAttribute { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.name.is_empty() { + len += 1; + } + if !self.value.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.r#type.http.v3.CookieAttribute", len)?; + if !self.name.is_empty() { + struct_ser.serialize_field("name", &self.name)?; + } + if !self.value.is_empty() { + struct_ser.serialize_field("value", &self.value)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for CookieAttribute { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "name", + "value", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Name, + Value, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "name" => Ok(GeneratedField::Name), + "value" => Ok(GeneratedField::Value), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = CookieAttribute; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.r#type.http.v3.CookieAttribute") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut name__ = None; + let mut value__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Name => { + if name__.is_some() { + return Err(serde::de::Error::duplicate_field("name")); + } + name__ = Some(map_.next_value()?); + } + GeneratedField::Value => { + if value__.is_some() { + return Err(serde::de::Error::duplicate_field("value")); + } + value__ = Some(map_.next_value()?); + } + } + } + Ok(CookieAttribute { + name: name__.unwrap_or_default(), + value: value__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.r#type.http.v3.CookieAttribute", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for PathTransformation { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/src/generated/envoy.r#type.matcher.v3.rs b/src/generated/envoy.r#type.matcher.v3.rs index d4a8b07..f44edac 100644 --- a/src/generated/envoy.r#type.matcher.v3.rs +++ b/src/generated/envoy.r#type.matcher.v3.rs @@ -1,4 +1,24 @@ // This file is @generated by prost-build. +/// Match an IP against a repeated CIDR range. This matcher is intended to be +/// used in other matchers, for example in the filter state matcher to match a +/// filter state object as an IP. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AddressMatcher { + #[prost(message, repeated, tag = "1")] + pub ranges: ::prost::alloc::vec::Vec< + super::super::super::super::xds::core::v3::CidrRange, + >, +} +impl ::prost::Name for AddressMatcher { + const NAME: &'static str = "AddressMatcher"; + const PACKAGE: &'static str = "envoy.type.matcher.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.type.matcher.v3.AddressMatcher".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.type.matcher.v3.AddressMatcher".into() + } +} /// A regex matcher designed for safety when used with untrusted input. #[derive(Clone, PartialEq, ::prost::Message)] pub struct RegexMatcher { @@ -113,9 +133,10 @@ impl ::prost::Name for RegexMatchAndSubstitute { /// \[#next-free-field: 9\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct StringMatcher { - /// If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. This - /// has no effect for the safe_regex match. - /// For example, the matcher ``data`` will match both input string ``Data`` and ``data`` if set to true. + /// If ``true``, indicates the exact/prefix/suffix/contains matching should be case insensitive. This + /// has no effect for the ``safe_regex`` match. + /// For example, the matcher ``data`` will match both input string ``Data`` and ``data`` if this option + /// is set to ``true``. #[prost(bool, tag = "6")] pub ignore_case: bool, #[prost(oneof = "string_matcher::MatchPattern", tags = "1, 2, 3, 5, 7, 8")] @@ -133,7 +154,10 @@ pub mod string_matcher { #[prost(string, tag = "1")] Exact(::prost::alloc::string::String), /// The input string must have the prefix specified here. - /// Note: empty prefix is not allowed, please use regex instead. + /// + /// .. note:: + /// + /// Empty prefix match is not allowed, please use ``safe_regex`` instead. /// /// Examples: /// @@ -141,7 +165,10 @@ pub mod string_matcher { #[prost(string, tag = "2")] Prefix(::prost::alloc::string::String), /// The input string must have the suffix specified here. - /// Note: empty prefix is not allowed, please use regex instead. + /// + /// .. note:: + /// + /// Empty suffix match is not allowed, please use ``safe_regex`` instead. /// /// Examples: /// @@ -152,7 +179,10 @@ pub mod string_matcher { #[prost(message, tag = "5")] SafeRegex(super::RegexMatcher), /// The input string must have the substring specified here. - /// Note: empty contains match is not allowed, please use regex instead. + /// + /// .. note:: + /// + /// Empty contains match is not allowed, please use ``safe_regex`` instead. /// /// Examples: /// @@ -197,7 +227,7 @@ pub struct FilterStateMatcher { /// The filter state key to retrieve the object. #[prost(string, tag = "1")] pub key: ::prost::alloc::string::String, - #[prost(oneof = "filter_state_matcher::Matcher", tags = "2")] + #[prost(oneof = "filter_state_matcher::Matcher", tags = "2, 3")] pub matcher: ::core::option::Option, } /// Nested message and enum types in `FilterStateMatcher`. @@ -207,6 +237,9 @@ pub mod filter_state_matcher { /// Matches the filter state object as a string value. #[prost(message, tag = "2")] StringMatch(super::StringMatcher), + /// Matches the filter state object as a ip Instance. + #[prost(message, tag = "3")] + AddressMatch(super::AddressMatcher), } } impl ::prost::Name for FilterStateMatcher { @@ -467,13 +500,13 @@ impl ::prost::Name for OrMatcher { /// \[#next-major-version: MetadataMatcher should use StructMatcher\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct MetadataMatcher { - /// The filter name to retrieve the Struct from the Metadata. + /// The filter name to retrieve the ``Struct`` from the ``Metadata``. #[prost(string, tag = "1")] pub filter: ::prost::alloc::string::String, - /// The path to retrieve the Value from the Struct. + /// The path to retrieve the ``Value`` from the ``Struct``. #[prost(message, repeated, tag = "2")] pub path: ::prost::alloc::vec::Vec, - /// The MetadataMatcher is matched if the value retrieved by path is matched to this value. + /// The ``MetadataMatcher`` is matched if the value retrieved by path is matched to this value. #[prost(message, optional, tag = "3")] pub value: ::core::option::Option, /// If true, the match result will be inverted. @@ -482,9 +515,11 @@ pub struct MetadataMatcher { } /// Nested message and enum types in `MetadataMatcher`. pub mod metadata_matcher { - /// Specifies the segment in a path to retrieve value from Metadata. - /// Note: Currently it's not supported to retrieve a value from a list in Metadata. This means that - /// if the segment key refers to a list, it has to be the last segment in a path. + /// Specifies the segment in a path to retrieve value from ``Metadata``. + /// + /// .. note:: + /// Currently it's not supported to retrieve a value from a list in ``Metadata``. This means that + /// if the segment key refers to a list, it has to be the last segment in a path. #[derive(Clone, PartialEq, ::prost::Message)] pub struct PathSegment { #[prost(oneof = "path_segment::Segment", tags = "1")] @@ -494,7 +529,7 @@ pub mod metadata_matcher { pub mod path_segment { #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Segment { - /// If specified, use the key to retrieve the value in a Struct. + /// If specified, use the key to retrieve the value in a ``Struct``. #[prost(string, tag = "1")] Key(::prost::alloc::string::String), } diff --git a/src/generated/envoy.r#type.matcher.v3.serde.rs b/src/generated/envoy.r#type.matcher.v3.serde.rs index ab1e4fa..dc4e1de 100644 --- a/src/generated/envoy.r#type.matcher.v3.serde.rs +++ b/src/generated/envoy.r#type.matcher.v3.serde.rs @@ -1,3 +1,94 @@ +impl serde::Serialize for AddressMatcher { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.ranges.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.r#type.matcher.v3.AddressMatcher", len)?; + if !self.ranges.is_empty() { + struct_ser.serialize_field("ranges", &self.ranges)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for AddressMatcher { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "ranges", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Ranges, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "ranges" => Ok(GeneratedField::Ranges), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = AddressMatcher; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.r#type.matcher.v3.AddressMatcher") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut ranges__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Ranges => { + if ranges__.is_some() { + return Err(serde::de::Error::duplicate_field("ranges")); + } + ranges__ = Some(map_.next_value()?); + } + } + } + Ok(AddressMatcher { + ranges: ranges__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.r#type.matcher.v3.AddressMatcher", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for DoubleMatcher { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -129,6 +220,9 @@ impl serde::Serialize for FilterStateMatcher { filter_state_matcher::Matcher::StringMatch(v) => { struct_ser.serialize_field("string_match", v)?; } + filter_state_matcher::Matcher::AddressMatch(v) => { + struct_ser.serialize_field("address_match", v)?; + } } } struct_ser.end() @@ -144,12 +238,15 @@ impl<'de> serde::Deserialize<'de> for FilterStateMatcher { "key", "string_match", "stringMatch", + "address_match", + "addressMatch", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { Key, StringMatch, + AddressMatch, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -173,6 +270,7 @@ impl<'de> serde::Deserialize<'de> for FilterStateMatcher { match value { "key" => Ok(GeneratedField::Key), "stringMatch" | "string_match" => Ok(GeneratedField::StringMatch), + "addressMatch" | "address_match" => Ok(GeneratedField::AddressMatch), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -207,6 +305,13 @@ impl<'de> serde::Deserialize<'de> for FilterStateMatcher { return Err(serde::de::Error::duplicate_field("stringMatch")); } matcher__ = map_.next_value::<::std::option::Option<_>>()?.map(filter_state_matcher::Matcher::StringMatch) +; + } + GeneratedField::AddressMatch => { + if matcher__.is_some() { + return Err(serde::de::Error::duplicate_field("addressMatch")); + } + matcher__ = map_.next_value::<::std::option::Option<_>>()?.map(filter_state_matcher::Matcher::AddressMatch) ; } } diff --git a/src/generated/envoy.r#type.metadata.v3.rs b/src/generated/envoy.r#type.metadata.v3.rs index a749df3..c4f1b86 100644 --- a/src/generated/envoy.r#type.metadata.v3.rs +++ b/src/generated/envoy.r#type.metadata.v3.rs @@ -1,8 +1,8 @@ // This file is @generated by prost-build. -/// MetadataKey provides a general interface using ``key`` and ``path`` to retrieve value from -/// :ref:`Metadata `. +/// MetadataKey provides a way to retrieve values from +/// :ref:`Metadata ` using a ``key`` and a ``path``. /// -/// For example, for the following Metadata: +/// For example, consider the following Metadata: /// /// .. code-block:: yaml /// @@ -13,7 +13,7 @@ /// xyz: /// hello: envoy /// -/// The following MetadataKey will retrieve a string value "bar" from the Metadata. +/// The following MetadataKey would retrieve the string value "bar" from the Metadata: /// /// .. code-block:: yaml /// @@ -24,23 +24,25 @@ /// #[derive(Clone, PartialEq, ::prost::Message)] pub struct MetadataKey { - /// The key name of Metadata to retrieve the Struct from the metadata. - /// Typically, it represents a builtin subsystem or custom extension. + /// The key name of the Metadata from which to retrieve the Struct. + /// This typically represents a builtin subsystem or custom extension. #[prost(string, tag = "1")] pub key: ::prost::alloc::string::String, - /// The path to retrieve the Value from the Struct. It can be a prefix or a full path, - /// e.g. ``\[prop, xyz\]`` for a struct or ``\[prop, foo\]`` for a string in the example, - /// which depends on the particular scenario. + /// The path used to retrieve a specific Value from the Struct. + /// This can be either a prefix or a full path, depending on the use case. + /// For example, ``\[prop, xyz\]`` would retrieve a struct or ``\[prop, foo\]`` would retrieve a string + /// in the example above. /// - /// Note: Due to that only the key type segment is supported, the path can not specify a list - /// unless the list is the last segment. + /// .. note:: + /// Since only key-type segments are supported, a path cannot specify a list + /// unless the list is the last segment. #[prost(message, repeated, tag = "2")] pub path: ::prost::alloc::vec::Vec, } /// Nested message and enum types in `MetadataKey`. pub mod metadata_key { - /// Specifies the segment in a path to retrieve value from Metadata. - /// Currently it is only supported to specify the key, i.e. field name, as one segment of a path. + /// Specifies a segment in a path for retrieving values from Metadata. + /// Currently, only key-based segments (field names) are supported. #[derive(Clone, PartialEq, ::prost::Message)] pub struct PathSegment { #[prost(oneof = "path_segment::Segment", tags = "1")] @@ -50,7 +52,7 @@ pub mod metadata_key { pub mod path_segment { #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Segment { - /// If specified, use the key to retrieve the value in a Struct. + /// If specified, use this key to retrieve the value in a Struct. #[prost(string, tag = "1")] Key(::prost::alloc::string::String), } @@ -76,7 +78,7 @@ impl ::prost::Name for MetadataKey { "type.googleapis.com/envoy.type.metadata.v3.MetadataKey".into() } } -/// Describes what kind of metadata. +/// Describes different types of metadata sources. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct MetadataKind { #[prost(oneof = "metadata_kind::Kind", tags = "1, 2, 3, 4")] diff --git a/src/generated/envoy.r#type.v3.rs b/src/generated/envoy.r#type.v3.rs index bd683e7..291695f 100644 --- a/src/generated/envoy.r#type.v3.rs +++ b/src/generated/envoy.r#type.v3.rs @@ -179,61 +179,117 @@ pub enum StatusCode { /// Empty - This code not part of the HTTP status code specification, but it is needed for proto /// `enum` type. Empty = 0, + /// Continue - ``100`` status code. Continue = 100, + /// OK - ``200`` status code. Ok = 200, + /// Created - ``201`` status code. Created = 201, + /// Accepted - ``202`` status code. Accepted = 202, + /// NonAuthoritativeInformation - ``203`` status code. NonAuthoritativeInformation = 203, + /// NoContent - ``204`` status code. NoContent = 204, + /// ResetContent - ``205`` status code. ResetContent = 205, + /// PartialContent - ``206`` status code. PartialContent = 206, + /// MultiStatus - ``207`` status code. MultiStatus = 207, + /// AlreadyReported - ``208`` status code. AlreadyReported = 208, + /// IMUsed - ``226`` status code. ImUsed = 226, + /// MultipleChoices - ``300`` status code. MultipleChoices = 300, + /// MovedPermanently - ``301`` status code. MovedPermanently = 301, + /// Found - ``302`` status code. Found = 302, + /// SeeOther - ``303`` status code. SeeOther = 303, + /// NotModified - ``304`` status code. NotModified = 304, + /// UseProxy - ``305`` status code. UseProxy = 305, + /// TemporaryRedirect - ``307`` status code. TemporaryRedirect = 307, + /// PermanentRedirect - ``308`` status code. PermanentRedirect = 308, + /// BadRequest - ``400`` status code. BadRequest = 400, + /// Unauthorized - ``401`` status code. Unauthorized = 401, + /// PaymentRequired - ``402`` status code. PaymentRequired = 402, + /// Forbidden - ``403`` status code. Forbidden = 403, + /// NotFound - ``404`` status code. NotFound = 404, + /// MethodNotAllowed - ``405`` status code. MethodNotAllowed = 405, + /// NotAcceptable - ``406`` status code. NotAcceptable = 406, + /// ProxyAuthenticationRequired - ``407`` status code. ProxyAuthenticationRequired = 407, + /// RequestTimeout - ``408`` status code. RequestTimeout = 408, + /// Conflict - ``409`` status code. Conflict = 409, + /// Gone - ``410`` status code. Gone = 410, + /// LengthRequired - ``411`` status code. LengthRequired = 411, + /// PreconditionFailed - ``412`` status code. PreconditionFailed = 412, + /// PayloadTooLarge - ``413`` status code. PayloadTooLarge = 413, + /// URITooLong - ``414`` status code. UriTooLong = 414, + /// UnsupportedMediaType - ``415`` status code. UnsupportedMediaType = 415, + /// RangeNotSatisfiable - ``416`` status code. RangeNotSatisfiable = 416, + /// ExpectationFailed - ``417`` status code. ExpectationFailed = 417, + /// MisdirectedRequest - ``421`` status code. MisdirectedRequest = 421, + /// UnprocessableEntity - ``422`` status code. UnprocessableEntity = 422, + /// Locked - ``423`` status code. Locked = 423, + /// FailedDependency - ``424`` status code. FailedDependency = 424, + /// UpgradeRequired - ``426`` status code. UpgradeRequired = 426, + /// PreconditionRequired - ``428`` status code. PreconditionRequired = 428, + /// TooManyRequests - ``429`` status code. TooManyRequests = 429, + /// RequestHeaderFieldsTooLarge - ``431`` status code. RequestHeaderFieldsTooLarge = 431, + /// InternalServerError - ``500`` status code. InternalServerError = 500, + /// NotImplemented - ``501`` status code. NotImplemented = 501, + /// BadGateway - ``502`` status code. BadGateway = 502, + /// ServiceUnavailable - ``503`` status code. ServiceUnavailable = 503, + /// GatewayTimeout - ``504`` status code. GatewayTimeout = 504, + /// HTTPVersionNotSupported - ``505`` status code. HttpVersionNotSupported = 505, + /// VariantAlsoNegotiates - ``506`` status code. VariantAlsoNegotiates = 506, + /// InsufficientStorage - ``507`` status code. InsufficientStorage = 507, + /// LoopDetected - ``508`` status code. LoopDetected = 508, + /// NotExtended - ``510`` status code. NotExtended = 510, + /// NetworkAuthenticationRequired - ``511`` status code. NetworkAuthenticationRequired = 511, } impl StatusCode { diff --git a/src/generated/envoy.service.accesslog.v3.rs b/src/generated/envoy.service.accesslog.v3.rs index 249e90d..379f553 100644 --- a/src/generated/envoy.service.accesslog.v3.rs +++ b/src/generated/envoy.service.accesslog.v3.rs @@ -128,7 +128,7 @@ pub mod access_log_service_client { } impl AccessLogServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -149,13 +149,13 @@ pub mod access_log_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { AccessLogServiceClient::new(InterceptedService::new(inner, interceptor)) @@ -323,7 +323,7 @@ pub mod access_log_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -385,7 +385,9 @@ pub mod access_log_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.auth.v3.rs b/src/generated/envoy.service.auth.v3.rs index 56f570f..3b8df22 100644 --- a/src/generated/envoy.service.auth.v3.rs +++ b/src/generated/envoy.service.auth.v3.rs @@ -6,7 +6,7 @@ /// of the ``AttributeContext``. The ``AttributeContext`` is a collection of individual attributes /// supported by Envoy authorization system. /// [#comment: The following items are left out of this proto -/// Request.Auth field for jwt tokens +/// Request.Auth field for JWTs /// Request.Api for api management /// Origin peer that originated the request /// Caching Protocol @@ -448,7 +448,7 @@ pub mod authorization_client { } impl AuthorizationClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -469,13 +469,13 @@ pub mod authorization_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { AuthorizationClient::new(InterceptedService::new(inner, interceptor)) @@ -623,7 +623,7 @@ pub mod authorization_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -680,7 +680,9 @@ pub mod authorization_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.cluster.v3.rs b/src/generated/envoy.service.cluster.v3.rs index add8d5f..c2ad821 100644 --- a/src/generated/envoy.service.cluster.v3.rs +++ b/src/generated/envoy.service.cluster.v3.rs @@ -31,7 +31,7 @@ pub mod cluster_discovery_service_client { } impl ClusterDiscoveryServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -52,13 +52,13 @@ pub mod cluster_discovery_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { ClusterDiscoveryServiceClient::new( @@ -325,7 +325,7 @@ pub mod cluster_discovery_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -500,7 +500,9 @@ pub mod cluster_discovery_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.discovery.v3.rs b/src/generated/envoy.service.discovery.v3.rs index ec43e5b..277669d 100644 --- a/src/generated/envoy.service.discovery.v3.rs +++ b/src/generated/envoy.service.discovery.v3.rs @@ -47,17 +47,41 @@ impl ::prost::Name for ResourceName { "type.googleapis.com/envoy.service.discovery.v3.ResourceName".into() } } +/// \[#not-implemented-hide:\] +/// An error associated with a specific resource name, returned to the +/// client by the server. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ResourceError { + /// The name of the resource. + #[prost(message, optional, tag = "1")] + pub resource_name: ::core::option::Option, + /// The error reported for the resource. + #[prost(message, optional, tag = "2")] + pub error_detail: ::core::option::Option< + super::super::super::super::google::rpc::Status, + >, +} +impl ::prost::Name for ResourceError { + const NAME: &'static str = "ResourceError"; + const PACKAGE: &'static str = "envoy.service.discovery.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.service.discovery.v3.ResourceError".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.service.discovery.v3.ResourceError".into() + } +} /// A DiscoveryRequest requests a set of versioned resources of the same type for /// a given Envoy node on some API. /// \[#next-free-field: 8\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct DiscoveryRequest { - /// The version_info provided in the request messages will be the version_info + /// The ``version_info`` provided in the request messages will be the ``version_info`` /// received with the most recent successfully processed response or empty on /// the first request. It is expected that no new request is sent after a /// response is received until the Envoy instance is ready to ACK/NACK the new /// configuration. ACK/NACK takes place by returning the new API config version - /// as applied or the previous API config version respectively. Each type_url + /// as applied or the previous API config version respectively. Each ``type_url`` /// (see below) has an independent version associated with it. #[prost(string, tag = "1")] pub version_info: ::prost::alloc::string::String, @@ -66,10 +90,10 @@ pub struct DiscoveryRequest { pub node: ::core::option::Option, /// List of resources to subscribe to, e.g. list of cluster names or a route /// configuration name. If this is empty, all resources for the API are - /// returned. LDS/CDS may have empty resource_names, which will cause all + /// returned. LDS/CDS may have empty ``resource_names``, which will cause all /// resources for the Envoy instance to be returned. The LDS and CDS responses /// will then imply a number of resources that need to be fetched via EDS/RDS, - /// which will be explicitly enumerated in resource_names. + /// which will be explicitly enumerated in ``resource_names``. #[prost(string, repeated, tag = "3")] pub resource_names: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, /// \[#not-implemented-hide:\] @@ -77,21 +101,27 @@ pub struct DiscoveryRequest { /// parameters along with each resource name. Clients that populate this /// field must be able to handle responses from the server where resources /// are wrapped in a Resource message. - /// Note that it is legal for a request to have some resources listed - /// in ``resource_names`` and others in ``resource_locators``. + /// + /// .. note:: + /// It is legal for a request to have some resources listed + /// in ``resource_names`` and others in ``resource_locators``. + /// #[prost(message, repeated, tag = "7")] pub resource_locators: ::prost::alloc::vec::Vec, /// Type of the resource that is being requested, e.g. - /// "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment". This is implicit + /// ``type.googleapis.com/envoy.api.v2.ClusterLoadAssignment``. This is implicit /// in requests made via singleton xDS APIs such as CDS, LDS, etc. but is /// required for ADS. #[prost(string, tag = "4")] pub type_url: ::prost::alloc::string::String, - /// nonce corresponding to DiscoveryResponse being ACK/NACKed. See above - /// discussion on version_info and the DiscoveryResponse nonce comment. This - /// may be empty only if 1) this is a non-persistent-stream xDS such as HTTP, - /// or 2) the client has not yet accepted an update in this xDS stream (unlike - /// delta, where it is populated only for new explicit ACKs). + /// nonce corresponding to ``DiscoveryResponse`` being ACK/NACKed. See above + /// discussion on ``version_info`` and the ``DiscoveryResponse`` nonce comment. This + /// may be empty only if: + /// + /// * This is a non-persistent-stream xDS such as HTTP, or + /// * The client has not yet accepted an update in this xDS stream (unlike + /// delta, where it is populated only for new explicit ACKs). + /// #[prost(string, tag = "5")] pub response_nonce: ::prost::alloc::string::String, /// This is populated when the previous :ref:`DiscoveryResponse ` @@ -113,7 +143,7 @@ impl ::prost::Name for DiscoveryRequest { "type.googleapis.com/envoy.service.discovery.v3.DiscoveryRequest".into() } } -/// \[#next-free-field: 7\] +/// \[#next-free-field: 8\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct DiscoveryResponse { /// The version of the response data. @@ -127,30 +157,34 @@ pub struct DiscoveryResponse { /// \[#not-implemented-hide:\] /// Canary is used to support two Envoy command line flags: /// - /// * --terminate-on-canary-transition-failure. When set, Envoy is able to + /// * ``--terminate-on-canary-transition-failure``. When set, Envoy is able to /// terminate if it detects that configuration is stuck at canary. Consider /// this example sequence of updates: - /// - Management server applies a canary config successfully. - /// - Management server rolls back to a production config. - /// - Envoy rejects the new production config. + /// + /// * Management server applies a canary config successfully. + /// * Management server rolls back to a production config. + /// * Envoy rejects the new production config. + /// /// Since there is no sensible way to continue receiving configuration /// updates, Envoy will then terminate and apply production config from a /// clean slate. - /// * --dry-run-canary. When set, a canary response will never be applied, only + /// + /// * ``--dry-run-canary``. When set, a canary response will never be applied, only /// validated via a dry run. + /// #[prost(bool, tag = "3")] pub canary: bool, /// Type URL for resources. Identifies the xDS API when muxing over ADS. - /// Must be consistent with the type_url in the 'resources' repeated Any (if non-empty). + /// Must be consistent with the ``type_url`` in the 'resources' repeated Any (if non-empty). #[prost(string, tag = "4")] pub type_url: ::prost::alloc::string::String, /// For gRPC based subscriptions, the nonce provides a way to explicitly ack a - /// specific DiscoveryResponse in a following DiscoveryRequest. Additional + /// specific ``DiscoveryResponse`` in a following ``DiscoveryRequest``. Additional /// messages may have been sent by Envoy to the management server for the - /// previous version on the stream prior to this DiscoveryResponse, that were + /// previous version on the stream prior to this ``DiscoveryResponse``, that were /// unprocessed at response send time. The nonce allows the management server - /// to ignore any further DiscoveryRequests for the previous version until a - /// DiscoveryRequest bearing the nonce. The nonce is optional and is not + /// to ignore any further ``DiscoveryRequests`` for the previous version until a + /// ``DiscoveryRequest`` bearing the nonce. The nonce is optional and is not /// required for non-stream based xDS implementations. #[prost(string, tag = "5")] pub nonce: ::prost::alloc::string::String, @@ -159,6 +193,13 @@ pub struct DiscoveryResponse { pub control_plane: ::core::option::Option< super::super::super::config::core::v3::ControlPlane, >, + /// \[#not-implemented-hide:\] + /// Errors associated with specific resources. Clients are expected to + /// remember the most recent error for a given resource across responses; + /// the error condition is not considered to be cleared until a response is + /// received that contains the resource in the 'resources' field. + #[prost(message, repeated, tag = "7")] + pub resource_errors: ::prost::alloc::vec::Vec, } impl ::prost::Name for DiscoveryResponse { const NAME: &'static str = "DiscoveryResponse"; @@ -183,25 +224,28 @@ impl ::prost::Name for DiscoveryResponse { /// connected to it. /// /// In Delta xDS the nonce field is required and used to pair -/// DeltaDiscoveryResponse to a DeltaDiscoveryRequest ACK or NACK. -/// Optionally, a response message level system_version_info is present for +/// ``DeltaDiscoveryResponse`` to a ``DeltaDiscoveryRequest`` ACK or NACK. +/// Optionally, a response message level ``system_version_info`` is present for /// debugging purposes only. /// -/// DeltaDiscoveryRequest plays two independent roles. Any DeltaDiscoveryRequest -/// can be either or both of: \[1\] informing the server of what resources the -/// client has gained/lost interest in (using resource_names_subscribe and -/// resource_names_unsubscribe), or \[2\] (N)ACKing an earlier resource update from -/// the server (using response_nonce, with presence of error_detail making it a NACK). -/// Additionally, the first message (for a given type_url) of a reconnected gRPC stream +/// ``DeltaDiscoveryRequest`` plays two independent roles. Any ``DeltaDiscoveryRequest`` +/// can be either or both of: +/// +/// * Informing the server of what resources the client has gained/lost interest in +/// (using ``resource_names_subscribe`` and ``resource_names_unsubscribe``), or +/// * (N)ACKing an earlier resource update from the server (using ``response_nonce``, +/// with presence of ``error_detail`` making it a NACK). +/// +/// Additionally, the first message (for a given ``type_url``) of a reconnected gRPC stream /// has a third role: informing the server of the resources (and their versions) -/// that the client already possesses, using the initial_resource_versions field. +/// that the client already possesses, using the ``initial_resource_versions`` field. /// /// As with state-of-the-world, when multiple resource types are multiplexed (ADS), -/// all requests/acknowledgments/updates are logically walled off by type_url: +/// all requests/acknowledgments/updates are logically walled off by ``type_url``: /// a Cluster ACK exists in a completely separate world from a prior Route NACK. -/// In particular, initial_resource_versions being sent at the "start" of every -/// gRPC stream actually entails a message for each type_url, each with its own -/// initial_resource_versions. +/// In particular, ``initial_resource_versions`` being sent at the "start" of every +/// gRPC stream actually entails a message for each ``type_url``, each with its own +/// ``initial_resource_versions``. /// \[#next-free-field: 10\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct DeltaDiscoveryRequest { @@ -216,23 +260,24 @@ pub struct DeltaDiscoveryRequest { pub type_url: ::prost::alloc::string::String, /// DeltaDiscoveryRequests allow the client to add or remove individual /// resources to the set of tracked resources in the context of a stream. - /// All resource names in the resource_names_subscribe list are added to the - /// set of tracked resources and all resource names in the resource_names_unsubscribe + /// All resource names in the ``resource_names_subscribe`` list are added to the + /// set of tracked resources and all resource names in the ``resource_names_unsubscribe`` /// list are removed from the set of tracked resources. /// - /// *Unlike* state-of-the-world xDS, an empty resource_names_subscribe or - /// resource_names_unsubscribe list simply means that no resources are to be + /// *Unlike* state-of-the-world xDS, an empty ``resource_names_subscribe`` or + /// ``resource_names_unsubscribe`` list simply means that no resources are to be /// added or removed to the resource list. /// *Like* state-of-the-world xDS, the server must send updates for all tracked /// resources, but can also send updates for resources the client has not subscribed to. /// - /// NOTE: the server must respond with all resources listed in resource_names_subscribe, - /// even if it believes the client has the most recent version of them. The reason: - /// the client may have dropped them, but then regained interest before it had a chance - /// to send the unsubscribe message. See DeltaSubscriptionStateTest.RemoveThenAdd. + /// .. note:: + /// The server must respond with all resources listed in ``resource_names_subscribe``, + /// even if it believes the client has the most recent version of them. The reason: + /// the client may have dropped them, but then regained interest before it had a chance + /// to send the unsubscribe message. See DeltaSubscriptionStateTest.RemoveThenAdd. /// - /// These two fields can be set in any DeltaDiscoveryRequest, including ACKs - /// and initial_resource_versions. + /// These two fields can be set in any ``DeltaDiscoveryRequest``, including ACKs + /// and ``initial_resource_versions``. /// /// A list of Resource names to add to the list of tracked resources. #[prost(string, repeated, tag = "3")] @@ -247,23 +292,32 @@ pub struct DeltaDiscoveryRequest { /// \[#not-implemented-hide:\] /// Alternative to ``resource_names_subscribe`` field that allows specifying dynamic parameters /// along with each resource name. - /// Note that it is legal for a request to have some resources listed - /// in ``resource_names_subscribe`` and others in ``resource_locators_subscribe``. + /// + /// .. note:: + /// It is legal for a request to have some resources listed + /// in ``resource_names_subscribe`` and others in ``resource_locators_subscribe``. + /// #[prost(message, repeated, tag = "8")] pub resource_locators_subscribe: ::prost::alloc::vec::Vec, /// \[#not-implemented-hide:\] /// Alternative to ``resource_names_unsubscribe`` field that allows specifying dynamic parameters /// along with each resource name. - /// Note that it is legal for a request to have some resources listed - /// in ``resource_names_unsubscribe`` and others in ``resource_locators_unsubscribe``. + /// + /// .. note:: + /// It is legal for a request to have some resources listed + /// in ``resource_names_unsubscribe`` and others in ``resource_locators_unsubscribe``. + /// #[prost(message, repeated, tag = "9")] pub resource_locators_unsubscribe: ::prost::alloc::vec::Vec, /// Informs the server of the versions of the resources the xDS client knows of, to enable the /// client to continue the same logical xDS session even in the face of gRPC stream reconnection. - /// It will not be populated: \[1\] in the very first stream of a session, since the client will - /// not yet have any resources, \[2\] in any message after the first in a stream (for a given - /// type_url), since the server will already be correctly tracking the client's state. - /// (In ADS, the first message *of each type_url* of a reconnected stream populates this map.) + /// It will not be populated: + /// + /// * In the very first stream of a session, since the client will not yet have any resources. + /// * In any message after the first in a stream (for a given ``type_url``), since the server will + /// already be correctly tracking the client's state. + /// + /// (In ADS, the first message ``of each type_url`` of a reconnected stream populates this map.) /// The map's keys are names of xDS resources known to the xDS client. /// The map's values are opaque resource versions. #[prost(map = "string, string", tag = "5")] @@ -271,10 +325,10 @@ pub struct DeltaDiscoveryRequest { ::prost::alloc::string::String, ::prost::alloc::string::String, >, - /// When the DeltaDiscoveryRequest is a ACK or NACK message in response - /// to a previous DeltaDiscoveryResponse, the response_nonce must be the - /// nonce in the DeltaDiscoveryResponse. - /// Otherwise (unlike in DiscoveryRequest) response_nonce must be omitted. + /// When the ``DeltaDiscoveryRequest`` is a ACK or NACK message in response + /// to a previous ``DeltaDiscoveryResponse``, the ``response_nonce`` must be the + /// nonce in the ``DeltaDiscoveryResponse``. + /// Otherwise (unlike in ``DiscoveryRequest``) ``response_nonce`` must be omitted. #[prost(string, tag = "6")] pub response_nonce: ::prost::alloc::string::String, /// This is populated when the previous :ref:`DiscoveryResponse ` @@ -295,31 +349,31 @@ impl ::prost::Name for DeltaDiscoveryRequest { "type.googleapis.com/envoy.service.discovery.v3.DeltaDiscoveryRequest".into() } } -/// \[#next-free-field: 9\] +/// \[#next-free-field: 10\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct DeltaDiscoveryResponse { /// The version of the response data (used for debugging). #[prost(string, tag = "1")] pub system_version_info: ::prost::alloc::string::String, /// The response resources. These are typed resources, whose types must match - /// the type_url field. + /// the ``type_url`` field. #[prost(message, repeated, tag = "2")] pub resources: ::prost::alloc::vec::Vec, /// Type URL for resources. Identifies the xDS API when muxing over ADS. - /// Must be consistent with the type_url in the Any within 'resources' if 'resources' is non-empty. + /// Must be consistent with the ``type_url`` in the Any within 'resources' if 'resources' is non-empty. #[prost(string, tag = "4")] pub type_url: ::prost::alloc::string::String, - /// Resources names of resources that have be deleted and to be removed from the xDS Client. + /// Resource names of resources that have been deleted and to be removed from the xDS Client. /// Removed resources for missing resources can be ignored. #[prost(string, repeated, tag = "6")] pub removed_resources: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - /// Alternative to removed_resources that allows specifying which variant of + /// Alternative to ``removed_resources`` that allows specifying which variant of /// a resource is being removed. This variant must be used for any resource /// for which dynamic parameter constraints were sent to the client. #[prost(message, repeated, tag = "8")] pub removed_resource_names: ::prost::alloc::vec::Vec, - /// The nonce provides a way for DeltaDiscoveryRequests to uniquely - /// reference a DeltaDiscoveryResponse when (N)ACKing. The nonce is required. + /// The nonce provides a way for ``DeltaDiscoveryRequests`` to uniquely + /// reference a ``DeltaDiscoveryResponse`` when (N)ACKing. The nonce is required. #[prost(string, tag = "5")] pub nonce: ::prost::alloc::string::String, /// \[#not-implemented-hide:\] @@ -328,6 +382,15 @@ pub struct DeltaDiscoveryResponse { pub control_plane: ::core::option::Option< super::super::super::config::core::v3::ControlPlane, >, + /// \[#not-implemented-hide:\] + /// Errors associated with specific resources. + /// + /// .. note:: + /// A resource in this field with a status of NOT_FOUND should be treated the same as + /// a resource listed in the ``removed_resources`` or ``removed_resource_names`` fields. + /// + #[prost(message, repeated, tag = "9")] + pub resource_errors: ::prost::alloc::vec::Vec, } impl ::prost::Name for DeltaDiscoveryResponse { const NAME: &'static str = "DeltaDiscoveryResponse"; @@ -342,7 +405,7 @@ impl ::prost::Name for DeltaDiscoveryResponse { /// A set of dynamic parameter constraints associated with a variant of an individual xDS resource. /// These constraints determine whether the resource matches a subscription based on the set of /// dynamic parameters in the subscription, as specified in the -/// :ref:`ResourceLocator.dynamic_parameters` +/// :ref:`ResourceLocator.dynamic_parameters ` /// field. This allows xDS implementations (clients, servers, and caching proxies) to determine /// which variant of a resource is appropriate for a given client. #[derive(Clone, PartialEq, ::prost::Message)] @@ -478,7 +541,7 @@ pub struct Resource { /// configuration for the resource will be removed. /// /// The TTL can be refreshed or changed by sending a response that doesn't change the resource - /// version. In this case the resource field does not need to be populated, which allows for + /// version. In this case the ``resource`` field does not need to be populated, which allows for /// light-weight "heartbeat" updates to keep a resource with a TTL alive. /// /// The TTL feature is meant to support configurations that should be removed in the event of @@ -507,8 +570,11 @@ pub mod resource { #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct CacheControl { /// If true, xDS proxies may not cache this resource. - /// Note that this does not apply to clients other than xDS proxies, which must cache resources - /// for their own use, regardless of the value of this field. + /// + /// .. note:: + /// This does not apply to clients other than xDS proxies, which must cache resources + /// for their own use, regardless of the value of this field. + /// #[prost(bool, tag = "1")] pub do_not_cache: bool, } @@ -570,7 +636,7 @@ pub mod aggregated_discovery_service_client { } impl AggregatedDiscoveryServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -591,13 +657,13 @@ pub mod aggregated_discovery_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { AggregatedDiscoveryServiceClient::new( @@ -811,7 +877,7 @@ pub mod aggregated_discovery_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -932,7 +998,9 @@ pub mod aggregated_discovery_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.discovery.v3.serde.rs b/src/generated/envoy.service.discovery.v3.serde.rs index e2df3a0..17aef6a 100644 --- a/src/generated/envoy.service.discovery.v3.serde.rs +++ b/src/generated/envoy.service.discovery.v3.serde.rs @@ -335,6 +335,9 @@ impl serde::Serialize for DeltaDiscoveryResponse { if self.control_plane.is_some() { len += 1; } + if !self.resource_errors.is_empty() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.service.discovery.v3.DeltaDiscoveryResponse", len)?; if !self.system_version_info.is_empty() { struct_ser.serialize_field("system_version_info", &self.system_version_info)?; @@ -357,6 +360,9 @@ impl serde::Serialize for DeltaDiscoveryResponse { if let Some(v) = self.control_plane.as_ref() { struct_ser.serialize_field("control_plane", v)?; } + if !self.resource_errors.is_empty() { + struct_ser.serialize_field("resource_errors", &self.resource_errors)?; + } struct_ser.end() } } @@ -379,6 +385,8 @@ impl<'de> serde::Deserialize<'de> for DeltaDiscoveryResponse { "nonce", "control_plane", "controlPlane", + "resource_errors", + "resourceErrors", ]; #[allow(clippy::enum_variant_names)] @@ -390,6 +398,7 @@ impl<'de> serde::Deserialize<'de> for DeltaDiscoveryResponse { RemovedResourceNames, Nonce, ControlPlane, + ResourceErrors, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -418,6 +427,7 @@ impl<'de> serde::Deserialize<'de> for DeltaDiscoveryResponse { "removedResourceNames" | "removed_resource_names" => Ok(GeneratedField::RemovedResourceNames), "nonce" => Ok(GeneratedField::Nonce), "controlPlane" | "control_plane" => Ok(GeneratedField::ControlPlane), + "resourceErrors" | "resource_errors" => Ok(GeneratedField::ResourceErrors), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -444,6 +454,7 @@ impl<'de> serde::Deserialize<'de> for DeltaDiscoveryResponse { let mut removed_resource_names__ = None; let mut nonce__ = None; let mut control_plane__ = None; + let mut resource_errors__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::SystemVersionInfo => { @@ -488,6 +499,12 @@ impl<'de> serde::Deserialize<'de> for DeltaDiscoveryResponse { } control_plane__ = map_.next_value()?; } + GeneratedField::ResourceErrors => { + if resource_errors__.is_some() { + return Err(serde::de::Error::duplicate_field("resourceErrors")); + } + resource_errors__ = Some(map_.next_value()?); + } } } Ok(DeltaDiscoveryResponse { @@ -498,6 +515,7 @@ impl<'de> serde::Deserialize<'de> for DeltaDiscoveryResponse { removed_resource_names: removed_resource_names__.unwrap_or_default(), nonce: nonce__.unwrap_or_default(), control_plane: control_plane__, + resource_errors: resource_errors__.unwrap_or_default(), }) } } @@ -729,6 +747,9 @@ impl serde::Serialize for DiscoveryResponse { if self.control_plane.is_some() { len += 1; } + if !self.resource_errors.is_empty() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("envoy.service.discovery.v3.DiscoveryResponse", len)?; if !self.version_info.is_empty() { struct_ser.serialize_field("version_info", &self.version_info)?; @@ -748,6 +769,9 @@ impl serde::Serialize for DiscoveryResponse { if let Some(v) = self.control_plane.as_ref() { struct_ser.serialize_field("control_plane", v)?; } + if !self.resource_errors.is_empty() { + struct_ser.serialize_field("resource_errors", &self.resource_errors)?; + } struct_ser.end() } } @@ -767,6 +791,8 @@ impl<'de> serde::Deserialize<'de> for DiscoveryResponse { "nonce", "control_plane", "controlPlane", + "resource_errors", + "resourceErrors", ]; #[allow(clippy::enum_variant_names)] @@ -777,6 +803,7 @@ impl<'de> serde::Deserialize<'de> for DiscoveryResponse { TypeUrl, Nonce, ControlPlane, + ResourceErrors, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -804,6 +831,7 @@ impl<'de> serde::Deserialize<'de> for DiscoveryResponse { "typeUrl" | "type_url" => Ok(GeneratedField::TypeUrl), "nonce" => Ok(GeneratedField::Nonce), "controlPlane" | "control_plane" => Ok(GeneratedField::ControlPlane), + "resourceErrors" | "resource_errors" => Ok(GeneratedField::ResourceErrors), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -829,6 +857,7 @@ impl<'de> serde::Deserialize<'de> for DiscoveryResponse { let mut type_url__ = None; let mut nonce__ = None; let mut control_plane__ = None; + let mut resource_errors__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::VersionInfo => { @@ -867,6 +896,12 @@ impl<'de> serde::Deserialize<'de> for DiscoveryResponse { } control_plane__ = map_.next_value()?; } + GeneratedField::ResourceErrors => { + if resource_errors__.is_some() { + return Err(serde::de::Error::duplicate_field("resourceErrors")); + } + resource_errors__ = Some(map_.next_value()?); + } } } Ok(DiscoveryResponse { @@ -876,6 +911,7 @@ impl<'de> serde::Deserialize<'de> for DiscoveryResponse { type_url: type_url__.unwrap_or_default(), nonce: nonce__.unwrap_or_default(), control_plane: control_plane__, + resource_errors: resource_errors__.unwrap_or_default(), }) } } @@ -1611,6 +1647,116 @@ impl<'de> serde::Deserialize<'de> for resource::CacheControl { deserializer.deserialize_struct("envoy.service.discovery.v3.Resource.CacheControl", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for ResourceError { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.resource_name.is_some() { + len += 1; + } + if self.error_detail.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.service.discovery.v3.ResourceError", len)?; + if let Some(v) = self.resource_name.as_ref() { + struct_ser.serialize_field("resource_name", v)?; + } + if let Some(v) = self.error_detail.as_ref() { + struct_ser.serialize_field("error_detail", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ResourceError { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "resource_name", + "resourceName", + "error_detail", + "errorDetail", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ResourceName, + ErrorDetail, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "resourceName" | "resource_name" => Ok(GeneratedField::ResourceName), + "errorDetail" | "error_detail" => Ok(GeneratedField::ErrorDetail), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ResourceError; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.service.discovery.v3.ResourceError") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut resource_name__ = None; + let mut error_detail__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ResourceName => { + if resource_name__.is_some() { + return Err(serde::de::Error::duplicate_field("resourceName")); + } + resource_name__ = map_.next_value()?; + } + GeneratedField::ErrorDetail => { + if error_detail__.is_some() { + return Err(serde::de::Error::duplicate_field("errorDetail")); + } + error_detail__ = map_.next_value()?; + } + } + } + Ok(ResourceError { + resource_name: resource_name__, + error_detail: error_detail__, + }) + } + } + deserializer.deserialize_struct("envoy.service.discovery.v3.ResourceError", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for ResourceLocator { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/src/generated/envoy.service.endpoint.v3.rs b/src/generated/envoy.service.endpoint.v3.rs index 3fb4293..e2c0b65 100644 --- a/src/generated/envoy.service.endpoint.v3.rs +++ b/src/generated/envoy.service.endpoint.v3.rs @@ -30,7 +30,7 @@ pub mod endpoint_discovery_service_client { } impl EndpointDiscoveryServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -51,13 +51,13 @@ pub mod endpoint_discovery_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { EndpointDiscoveryServiceClient::new( @@ -327,7 +327,7 @@ pub mod endpoint_discovery_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -502,7 +502,9 @@ pub mod endpoint_discovery_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( @@ -569,7 +571,7 @@ pub mod locality_endpoint_discovery_service_client { } impl LocalityEndpointDiscoveryServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -590,13 +592,13 @@ pub mod locality_endpoint_discovery_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { LocalityEndpointDiscoveryServiceClient::new( @@ -775,7 +777,7 @@ pub mod locality_endpoint_discovery_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -847,7 +849,9 @@ pub mod locality_endpoint_discovery_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.event_reporting.v3.rs b/src/generated/envoy.service.event_reporting.v3.rs index 6a1abf0..d1589a6 100644 --- a/src/generated/envoy.service.event_reporting.v3.rs +++ b/src/generated/envoy.service.event_reporting.v3.rs @@ -90,7 +90,7 @@ pub mod event_reporting_service_client { } impl EventReportingServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -111,13 +111,13 @@ pub mod event_reporting_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { EventReportingServiceClient::new(InterceptedService::new(inner, interceptor)) @@ -288,7 +288,7 @@ pub mod event_reporting_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -350,7 +350,9 @@ pub mod event_reporting_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.ext_proc.v3.rs b/src/generated/envoy.service.ext_proc.v3.rs index 5068df8..a12b204 100644 --- a/src/generated/envoy.service.ext_proc.v3.rs +++ b/src/generated/envoy.service.ext_proc.v3.rs @@ -1,7 +1,44 @@ // This file is @generated by prost-build. +/// This message specifies the filter protocol configurations which will be sent to the ext_proc +/// server in a :ref:`ProcessingRequest `. +/// If the server does not support these protocol configurations, it may choose to close the gRPC stream. +/// If the server supports these protocol configurations, it should respond based on the API specifications. +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct ProtocolConfiguration { + /// Specify the filter configuration :ref:`request_body_mode + /// ` + #[prost( + enumeration = "super::super::super::extensions::filters::http::ext_proc::v3::processing_mode::BodySendMode", + tag = "1" + )] + pub request_body_mode: i32, + /// Specify the filter configuration :ref:`response_body_mode + /// ` + #[prost( + enumeration = "super::super::super::extensions::filters::http::ext_proc::v3::processing_mode::BodySendMode", + tag = "2" + )] + pub response_body_mode: i32, + /// Specify the filter configuration :ref:`send_body_without_waiting_for_header_response + /// ` + /// If the client is waiting for a header response from the server, setting ``true`` means the client will send body to the server + /// as they arrive. Setting ``false`` means the client will buffer the arrived data and not send it to the server immediately. + #[prost(bool, tag = "3")] + pub send_body_without_waiting_for_header_response: bool, +} +impl ::prost::Name for ProtocolConfiguration { + const NAME: &'static str = "ProtocolConfiguration"; + const PACKAGE: &'static str = "envoy.service.ext_proc.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.service.ext_proc.v3.ProtocolConfiguration".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.service.ext_proc.v3.ProtocolConfiguration".into() + } +} /// This represents the different types of messages that Envoy can send /// to an external processing server. -/// \[#next-free-field: 11\] +/// \[#next-free-field: 12\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProcessingRequest { /// Dynamic metadata associated with the request. @@ -31,6 +68,10 @@ pub struct ProcessingRequest { /// #[prost(bool, tag = "10")] pub observability_mode: bool, + /// Specify the filter protocol configurations to be sent to the server. + /// ``protocol_config`` is only encoded in the first ``ProcessingRequest`` message from the client to the server. + #[prost(message, optional, tag = "11")] + pub protocol_config: ::core::option::Option, /// Each request message will include one of the following sub-messages. Which /// ones are set for a particular HTTP request/response depend on the /// processing mode. @@ -88,8 +129,15 @@ impl ::prost::Name for ProcessingRequest { "type.googleapis.com/envoy.service.ext_proc.v3.ProcessingRequest".into() } } -/// For every ProcessingRequest received by the server with the ``observability_mode`` field -/// set to false, the server must send back exactly one ProcessingResponse message. +/// This represents the different types of messages the server may send back to Envoy +/// when the ``observability_mode`` field in the received ProcessingRequest is set to false. +/// +/// * If the corresponding ``BodySendMode`` in the +/// :ref:`processing_mode ` +/// is not set to ``FULL_DUPLEX_STREAMED``, then for every received ProcessingRequest, +/// the server must send back exactly one ProcessingResponse message. +/// * If it is set to ``FULL_DUPLEX_STREAMED``, the server must follow the API defined +/// for this mode to send the ProcessingResponse messages. /// \[#next-free-field: 11\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProcessingResponse { @@ -109,7 +157,10 @@ pub struct ProcessingResponse { /// It is also ignored by Envoy when the ext_proc filter config /// :ref:`allow_mode_override /// ` - /// is set to false. + /// is set to false, or + /// :ref:`send_body_without_waiting_for_header_response + /// ` + /// is set to true. #[prost(message, optional, tag = "9")] pub mode_override: ::core::option::Option< super::super::super::extensions::filters::http::ext_proc::v3::ProcessingMode, @@ -131,11 +182,13 @@ pub struct ProcessingResponse { pub override_message_timeout: ::core::option::Option< super::super::super::super::google::protobuf::Duration, >, + /// The response type that is sent by the server. #[prost(oneof = "processing_response::Response", tags = "1, 2, 3, 4, 5, 6, 7")] pub response: ::core::option::Option, } /// Nested message and enum types in `ProcessingResponse`. pub mod processing_response { + /// The response type that is sent by the server. #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Response { /// The server must send back this message in response to a message with the @@ -189,12 +242,8 @@ impl ::prost::Name for ProcessingResponse { pub struct HttpHeaders { /// The HTTP request headers. All header keys will be /// lower-cased, because HTTP header keys are case-insensitive. - /// The ``headers`` encoding is based on the runtime guard - /// envoy_reloadable_features_send_header_raw_value setting. - /// When it is true, the header value is encoded in the + /// The header value is encoded in the /// :ref:`raw_value ` field. - /// When it is false, the header value is encoded in the - /// :ref:`value ` field. #[prost(message, optional, tag = "1")] pub headers: ::core::option::Option< super::super::super::config::core::v3::HeaderMap, @@ -208,7 +257,7 @@ pub struct HttpHeaders { ::prost::alloc::string::String, super::super::super::super::google::protobuf::Struct, >, - /// If true, then there is no message body associated with this + /// If ``true``, then there is no message body associated with this /// request or response. #[prost(bool, tag = "3")] pub end_of_stream: bool, @@ -223,11 +272,16 @@ impl ::prost::Name for HttpHeaders { "type.googleapis.com/envoy.service.ext_proc.v3.HttpHeaders".into() } } -/// This message contains the message body that Envoy sends to the external server. +/// This message is sent to the external server when the HTTP request and +/// response bodies are received. #[derive(Clone, PartialEq, ::prost::Message)] pub struct HttpBody { + /// The contents of the body in the HTTP request/response. Note that in + /// streaming mode multiple ``HttpBody`` messages may be sent. #[prost(bytes = "vec", tag = "1")] pub body: ::prost::alloc::vec::Vec, + /// If ``true``, this will be the last ``HttpBody`` message that will be sent and no + /// trailers will be sent for the current request/response. #[prost(bool, tag = "2")] pub end_of_stream: bool, } @@ -241,15 +295,12 @@ impl ::prost::Name for HttpBody { "type.googleapis.com/envoy.service.ext_proc.v3.HttpBody".into() } } -/// This message contains the trailers. +/// This message is sent to the external server when the HTTP request and +/// response trailers are received. #[derive(Clone, PartialEq, ::prost::Message)] pub struct HttpTrailers { - /// The ``trailers`` encoding is based on the runtime guard - /// envoy_reloadable_features_send_header_raw_value setting. - /// When it is true, the header value is encoded in the + /// The header value is encoded in the /// :ref:`raw_value ` field. - /// When it is false, the header value is encoded in the - /// :ref:`value ` field. #[prost(message, optional, tag = "1")] pub trailers: ::core::option::Option< super::super::super::config::core::v3::HeaderMap, @@ -265,9 +316,12 @@ impl ::prost::Name for HttpTrailers { "type.googleapis.com/envoy.service.ext_proc.v3.HttpTrailers".into() } } -/// This message must be sent in response to an HttpHeaders message. +/// This message is sent by the external server to Envoy after ``HttpHeaders`` was +/// sent to it. #[derive(Clone, PartialEq, ::prost::Message)] pub struct HeadersResponse { + /// Details the modifications (if any) to be made by Envoy to the current + /// request/response. #[prost(message, optional, tag = "1")] pub response: ::core::option::Option, } @@ -281,37 +335,42 @@ impl ::prost::Name for HeadersResponse { "type.googleapis.com/envoy.service.ext_proc.v3.HeadersResponse".into() } } -/// This message must be sent in response to an HttpTrailers message. +/// This message is sent by the external server to Envoy after ``HttpBody`` was +/// sent to it. #[derive(Clone, PartialEq, ::prost::Message)] -pub struct TrailersResponse { - /// Instructions on how to manipulate the trailers +pub struct BodyResponse { + /// Details the modifications (if any) to be made by Envoy to the current + /// request/response. #[prost(message, optional, tag = "1")] - pub header_mutation: ::core::option::Option, + pub response: ::core::option::Option, } -impl ::prost::Name for TrailersResponse { - const NAME: &'static str = "TrailersResponse"; +impl ::prost::Name for BodyResponse { + const NAME: &'static str = "BodyResponse"; const PACKAGE: &'static str = "envoy.service.ext_proc.v3"; fn full_name() -> ::prost::alloc::string::String { - "envoy.service.ext_proc.v3.TrailersResponse".into() + "envoy.service.ext_proc.v3.BodyResponse".into() } fn type_url() -> ::prost::alloc::string::String { - "type.googleapis.com/envoy.service.ext_proc.v3.TrailersResponse".into() + "type.googleapis.com/envoy.service.ext_proc.v3.BodyResponse".into() } } -/// This message must be sent in response to an HttpBody message. +/// This message is sent by the external server to Envoy after ``HttpTrailers`` was +/// sent to it. #[derive(Clone, PartialEq, ::prost::Message)] -pub struct BodyResponse { +pub struct TrailersResponse { + /// Details the modifications (if any) to be made by Envoy to the current + /// request/response trailers. #[prost(message, optional, tag = "1")] - pub response: ::core::option::Option, + pub header_mutation: ::core::option::Option, } -impl ::prost::Name for BodyResponse { - const NAME: &'static str = "BodyResponse"; +impl ::prost::Name for TrailersResponse { + const NAME: &'static str = "TrailersResponse"; const PACKAGE: &'static str = "envoy.service.ext_proc.v3"; fn full_name() -> ::prost::alloc::string::String { - "envoy.service.ext_proc.v3.BodyResponse".into() + "envoy.service.ext_proc.v3.TrailersResponse".into() } fn type_url() -> ::prost::alloc::string::String { - "type.googleapis.com/envoy.service.ext_proc.v3.BodyResponse".into() + "type.googleapis.com/envoy.service.ext_proc.v3.TrailersResponse".into() } } /// This message contains common fields between header and body responses. @@ -340,12 +399,8 @@ pub struct CommonResponse { /// Add new trailers to the message. This may be used when responding to either a /// HttpHeaders or HttpBody message, but only if this message is returned /// along with the CONTINUE_AND_REPLACE status. - /// The ``trailers`` encoding is based on the runtime guard - /// envoy_reloadable_features_send_header_raw_value setting. - /// When it is true, the header value is encoded in the + /// The header value is encoded in the /// :ref:`raw_value ` field. - /// When it is false, the header value is encoded in the - /// :ref:`value ` field. #[prost(message, optional, tag = "4")] pub trailers: ::core::option::Option< super::super::super::config::core::v3::HeaderMap, @@ -359,6 +414,7 @@ pub struct CommonResponse { } /// Nested message and enum types in `CommonResponse`. pub mod common_response { + /// The status of the response. #[derive( Clone, Copy, @@ -430,7 +486,7 @@ impl ::prost::Name for CommonResponse { /// \[#next-free-field: 6\] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ImmediateResponse { - /// The response code to return + /// The response code to return. #[prost(message, optional, tag = "1")] pub status: ::core::option::Option, /// Apply changes to the default headers, which will include content-type. @@ -462,7 +518,7 @@ impl ::prost::Name for ImmediateResponse { /// This message specifies a gRPC status for an ImmediateResponse message. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct GrpcStatus { - /// The actual gRPC status + /// The actual gRPC status. #[prost(uint32, tag = "1")] pub status: u32, } @@ -483,12 +539,8 @@ pub struct HeaderMutation { /// Add or replace HTTP headers. Attempts to set the value of /// any ``x-envoy`` header, and attempts to set the ``:method``, /// ``:authority``, ``:scheme``, or ``host`` headers will be ignored. - /// The ``set_headers`` encoding is based on the runtime guard - /// envoy_reloadable_features_send_header_raw_value setting. - /// When it is true, the header value is encoded in the + /// The header value is encoded in the /// :ref:`raw_value ` field. - /// When it is false, the header value is encoded in the - /// :ref:`value ` field. #[prost(message, repeated, tag = "1")] pub set_headers: ::prost::alloc::vec::Vec< super::super::super::config::core::v3::HeaderValueOption, @@ -508,23 +560,58 @@ impl ::prost::Name for HeaderMutation { "type.googleapis.com/envoy.service.ext_proc.v3.HeaderMutation".into() } } -/// Replace the entire message body chunk received in the corresponding -/// HttpBody message with this new body, or clear the body. +/// The body response message corresponding to FULL_DUPLEX_STREAMED body mode. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StreamedBodyResponse { + /// The body response chunk that will be passed to the upstream/downstream by Envoy. + #[prost(bytes = "vec", tag = "1")] + pub body: ::prost::alloc::vec::Vec, + /// The server sets this flag to true if it has received a body request with + /// :ref:`end_of_stream ` set to true, + /// and this is the last chunk of body responses. + #[prost(bool, tag = "2")] + pub end_of_stream: bool, +} +impl ::prost::Name for StreamedBodyResponse { + const NAME: &'static str = "StreamedBodyResponse"; + const PACKAGE: &'static str = "envoy.service.ext_proc.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.service.ext_proc.v3.StreamedBodyResponse".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.service.ext_proc.v3.StreamedBodyResponse".into() + } +} +/// This message specifies the body mutation the server sends to Envoy. #[derive(Clone, PartialEq, ::prost::Message)] pub struct BodyMutation { - #[prost(oneof = "body_mutation::Mutation", tags = "1, 2")] + /// The type of mutation for the body. + #[prost(oneof = "body_mutation::Mutation", tags = "1, 2, 3")] pub mutation: ::core::option::Option, } /// Nested message and enum types in `BodyMutation`. pub mod body_mutation { + /// The type of mutation for the body. #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Mutation { - /// The entire body to replace + /// The entire body to replace. + /// Should only be used when the corresponding ``BodySendMode`` in the + /// :ref:`processing_mode ` + /// is not set to ``FULL_DUPLEX_STREAMED``. #[prost(bytes, tag = "1")] Body(::prost::alloc::vec::Vec), - /// Clear the corresponding body chunk + /// Clear the corresponding body chunk. + /// Should only be used when the corresponding ``BodySendMode`` in the + /// :ref:`processing_mode ` + /// is not set to ``FULL_DUPLEX_STREAMED``. + /// Clear the corresponding body chunk. #[prost(bool, tag = "2")] ClearBody(bool), + /// Must be used when the corresponding ``BodySendMode`` in the + /// :ref:`processing_mode ` + /// is set to ``FULL_DUPLEX_STREAMED``. + #[prost(message, tag = "3")] + StreamedResponse(super::StreamedBodyResponse), } } impl ::prost::Name for BodyMutation { @@ -548,13 +635,38 @@ pub mod external_processor_client { )] use tonic::codegen::*; use tonic::codegen::http::Uri; + /// A service that can access and modify HTTP requests and responses + /// as part of a filter chain. + /// The overall external processing protocol works like this: + /// + /// 1. Envoy sends to the service information about the HTTP request. + /// 2. The service sends back a ProcessingResponse message that directs Envoy + /// to either stop processing, continue without it, or send it the + /// next chunk of the message body. + /// 3. If so requested, Envoy sends the server the message body in chunks, + /// or the entire body at once. In either case, the server may send back + /// a ProcessingResponse for each message it receives, or wait for certain amount + /// of body chunks received before streams back the ProcessingResponse messages. + /// 4. If so requested, Envoy sends the server the HTTP trailers, + /// and the server sends back a ProcessingResponse. + /// 5. At this point, request processing is done, and we pick up again + /// at step 1 when Envoy receives a response from the upstream server. + /// 6. At any point above, if the server closes the gRPC stream cleanly, + /// then Envoy proceeds without consulting the server. + /// 7. At any point above, if the server closes the gRPC stream with an error, + /// then Envoy returns a 500 error to the client, unless the filter + /// was configured to ignore errors. + /// + /// In other words, the process is a request/response conversation, but + /// using a gRPC stream to make it easier for the server to + /// maintain state. #[derive(Debug, Clone)] pub struct ExternalProcessorClient { inner: tonic::client::Grpc, } impl ExternalProcessorClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -575,13 +687,13 @@ pub mod external_processor_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { ExternalProcessorClient::new(InterceptedService::new(inner, interceptor)) @@ -680,6 +792,31 @@ pub mod external_processor_server { request: tonic::Request>, ) -> std::result::Result, tonic::Status>; } + /// A service that can access and modify HTTP requests and responses + /// as part of a filter chain. + /// The overall external processing protocol works like this: + /// + /// 1. Envoy sends to the service information about the HTTP request. + /// 2. The service sends back a ProcessingResponse message that directs Envoy + /// to either stop processing, continue without it, or send it the + /// next chunk of the message body. + /// 3. If so requested, Envoy sends the server the message body in chunks, + /// or the entire body at once. In either case, the server may send back + /// a ProcessingResponse for each message it receives, or wait for certain amount + /// of body chunks received before streams back the ProcessingResponse messages. + /// 4. If so requested, Envoy sends the server the HTTP trailers, + /// and the server sends back a ProcessingResponse. + /// 5. At this point, request processing is done, and we pick up again + /// at step 1 when Envoy receives a response from the upstream server. + /// 6. At any point above, if the server closes the gRPC stream cleanly, + /// then Envoy proceeds without consulting the server. + /// 7. At any point above, if the server closes the gRPC stream with an error, + /// then Envoy returns a 500 error to the client, unless the filter + /// was configured to ignore errors. + /// + /// In other words, the process is a request/response conversation, but + /// using a gRPC stream to make it easier for the server to + /// maintain state. #[derive(Debug)] pub struct ExternalProcessorServer { inner: Arc, @@ -745,7 +882,7 @@ pub mod external_processor_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -806,7 +943,9 @@ pub mod external_processor_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.ext_proc.v3.serde.rs b/src/generated/envoy.service.ext_proc.v3.serde.rs index d98269d..c2bb0c2 100644 --- a/src/generated/envoy.service.ext_proc.v3.serde.rs +++ b/src/generated/envoy.service.ext_proc.v3.serde.rs @@ -20,6 +20,9 @@ impl serde::Serialize for BodyMutation { body_mutation::Mutation::ClearBody(v) => { struct_ser.serialize_field("clear_body", v)?; } + body_mutation::Mutation::StreamedResponse(v) => { + struct_ser.serialize_field("streamed_response", v)?; + } } } struct_ser.end() @@ -35,12 +38,15 @@ impl<'de> serde::Deserialize<'de> for BodyMutation { "body", "clear_body", "clearBody", + "streamed_response", + "streamedResponse", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { Body, ClearBody, + StreamedResponse, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -64,6 +70,7 @@ impl<'de> serde::Deserialize<'de> for BodyMutation { match value { "body" => Ok(GeneratedField::Body), "clearBody" | "clear_body" => Ok(GeneratedField::ClearBody), + "streamedResponse" | "streamed_response" => Ok(GeneratedField::StreamedResponse), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -98,6 +105,13 @@ impl<'de> serde::Deserialize<'de> for BodyMutation { } mutation__ = map_.next_value::<::std::option::Option<_>>()?.map(body_mutation::Mutation::ClearBody); } + GeneratedField::StreamedResponse => { + if mutation__.is_some() { + return Err(serde::de::Error::duplicate_field("streamedResponse")); + } + mutation__ = map_.next_value::<::std::option::Option<_>>()?.map(body_mutation::Mutation::StreamedResponse) +; + } } } Ok(BodyMutation { @@ -1241,6 +1255,9 @@ impl serde::Serialize for ProcessingRequest { if self.observability_mode { len += 1; } + if self.protocol_config.is_some() { + len += 1; + } if self.request.is_some() { len += 1; } @@ -1254,6 +1271,9 @@ impl serde::Serialize for ProcessingRequest { if self.observability_mode { struct_ser.serialize_field("observability_mode", &self.observability_mode)?; } + if let Some(v) = self.protocol_config.as_ref() { + struct_ser.serialize_field("protocol_config", v)?; + } if let Some(v) = self.request.as_ref() { match v { processing_request::Request::RequestHeaders(v) => { @@ -1291,6 +1311,8 @@ impl<'de> serde::Deserialize<'de> for ProcessingRequest { "attributes", "observability_mode", "observabilityMode", + "protocol_config", + "protocolConfig", "request_headers", "requestHeaders", "response_headers", @@ -1310,6 +1332,7 @@ impl<'de> serde::Deserialize<'de> for ProcessingRequest { MetadataContext, Attributes, ObservabilityMode, + ProtocolConfig, RequestHeaders, ResponseHeaders, RequestBody, @@ -1340,6 +1363,7 @@ impl<'de> serde::Deserialize<'de> for ProcessingRequest { "metadataContext" | "metadata_context" => Ok(GeneratedField::MetadataContext), "attributes" => Ok(GeneratedField::Attributes), "observabilityMode" | "observability_mode" => Ok(GeneratedField::ObservabilityMode), + "protocolConfig" | "protocol_config" => Ok(GeneratedField::ProtocolConfig), "requestHeaders" | "request_headers" => Ok(GeneratedField::RequestHeaders), "responseHeaders" | "response_headers" => Ok(GeneratedField::ResponseHeaders), "requestBody" | "request_body" => Ok(GeneratedField::RequestBody), @@ -1368,6 +1392,7 @@ impl<'de> serde::Deserialize<'de> for ProcessingRequest { let mut metadata_context__ = None; let mut attributes__ = None; let mut observability_mode__ = None; + let mut protocol_config__ = None; let mut request__ = None; while let Some(k) = map_.next_key()? { match k { @@ -1391,6 +1416,12 @@ impl<'de> serde::Deserialize<'de> for ProcessingRequest { } observability_mode__ = Some(map_.next_value()?); } + GeneratedField::ProtocolConfig => { + if protocol_config__.is_some() { + return Err(serde::de::Error::duplicate_field("protocolConfig")); + } + protocol_config__ = map_.next_value()?; + } GeneratedField::RequestHeaders => { if request__.is_some() { return Err(serde::de::Error::duplicate_field("requestHeaders")); @@ -1439,6 +1470,7 @@ impl<'de> serde::Deserialize<'de> for ProcessingRequest { metadata_context: metadata_context__, attributes: attributes__.unwrap_or_default(), observability_mode: observability_mode__.unwrap_or_default(), + protocol_config: protocol_config__, request: request__, }) } @@ -1681,6 +1713,251 @@ impl<'de> serde::Deserialize<'de> for ProcessingResponse { deserializer.deserialize_struct("envoy.service.ext_proc.v3.ProcessingResponse", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for ProtocolConfiguration { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.request_body_mode != 0 { + len += 1; + } + if self.response_body_mode != 0 { + len += 1; + } + if self.send_body_without_waiting_for_header_response { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.service.ext_proc.v3.ProtocolConfiguration", len)?; + if self.request_body_mode != 0 { + let v = super::super::super::extensions::filters::http::ext_proc::v3::processing_mode::BodySendMode::try_from(self.request_body_mode) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", self.request_body_mode)))?; + struct_ser.serialize_field("request_body_mode", &v)?; + } + if self.response_body_mode != 0 { + let v = super::super::super::extensions::filters::http::ext_proc::v3::processing_mode::BodySendMode::try_from(self.response_body_mode) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", self.response_body_mode)))?; + struct_ser.serialize_field("response_body_mode", &v)?; + } + if self.send_body_without_waiting_for_header_response { + struct_ser.serialize_field("send_body_without_waiting_for_header_response", &self.send_body_without_waiting_for_header_response)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ProtocolConfiguration { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "request_body_mode", + "requestBodyMode", + "response_body_mode", + "responseBodyMode", + "send_body_without_waiting_for_header_response", + "sendBodyWithoutWaitingForHeaderResponse", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + RequestBodyMode, + ResponseBodyMode, + SendBodyWithoutWaitingForHeaderResponse, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "requestBodyMode" | "request_body_mode" => Ok(GeneratedField::RequestBodyMode), + "responseBodyMode" | "response_body_mode" => Ok(GeneratedField::ResponseBodyMode), + "sendBodyWithoutWaitingForHeaderResponse" | "send_body_without_waiting_for_header_response" => Ok(GeneratedField::SendBodyWithoutWaitingForHeaderResponse), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ProtocolConfiguration; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.service.ext_proc.v3.ProtocolConfiguration") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut request_body_mode__ = None; + let mut response_body_mode__ = None; + let mut send_body_without_waiting_for_header_response__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::RequestBodyMode => { + if request_body_mode__.is_some() { + return Err(serde::de::Error::duplicate_field("requestBodyMode")); + } + request_body_mode__ = Some(map_.next_value::()? as i32); + } + GeneratedField::ResponseBodyMode => { + if response_body_mode__.is_some() { + return Err(serde::de::Error::duplicate_field("responseBodyMode")); + } + response_body_mode__ = Some(map_.next_value::()? as i32); + } + GeneratedField::SendBodyWithoutWaitingForHeaderResponse => { + if send_body_without_waiting_for_header_response__.is_some() { + return Err(serde::de::Error::duplicate_field("sendBodyWithoutWaitingForHeaderResponse")); + } + send_body_without_waiting_for_header_response__ = Some(map_.next_value()?); + } + } + } + Ok(ProtocolConfiguration { + request_body_mode: request_body_mode__.unwrap_or_default(), + response_body_mode: response_body_mode__.unwrap_or_default(), + send_body_without_waiting_for_header_response: send_body_without_waiting_for_header_response__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.service.ext_proc.v3.ProtocolConfiguration", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for StreamedBodyResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.body.is_empty() { + len += 1; + } + if self.end_of_stream { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.service.ext_proc.v3.StreamedBodyResponse", len)?; + if !self.body.is_empty() { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("body", pbjson::private::base64::encode(&self.body).as_str())?; + } + if self.end_of_stream { + struct_ser.serialize_field("end_of_stream", &self.end_of_stream)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for StreamedBodyResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "body", + "end_of_stream", + "endOfStream", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Body, + EndOfStream, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "body" => Ok(GeneratedField::Body), + "endOfStream" | "end_of_stream" => Ok(GeneratedField::EndOfStream), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = StreamedBodyResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.service.ext_proc.v3.StreamedBodyResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut body__ = None; + let mut end_of_stream__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Body => { + if body__.is_some() { + return Err(serde::de::Error::duplicate_field("body")); + } + body__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + GeneratedField::EndOfStream => { + if end_of_stream__.is_some() { + return Err(serde::de::Error::duplicate_field("endOfStream")); + } + end_of_stream__ = Some(map_.next_value()?); + } + } + } + Ok(StreamedBodyResponse { + body: body__.unwrap_or_default(), + end_of_stream: end_of_stream__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.service.ext_proc.v3.StreamedBodyResponse", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for TrailersResponse { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/src/generated/envoy.service.extension.v3.rs b/src/generated/envoy.service.extension.v3.rs index 1c88ab2..cb3db1c 100644 --- a/src/generated/envoy.service.extension.v3.rs +++ b/src/generated/envoy.service.extension.v3.rs @@ -25,6 +25,30 @@ pub mod extension_config_discovery_service_client { )] use tonic::codegen::*; use tonic::codegen::http::Uri; + /// A service that supports dynamic configuration updates for a specific filter. + /// Currently, ECDS is supported for network filters, HTTP filters, UDP session filters, and listener filters. + /// Please check :ref:`Extension Config Discovery Service (ECDS) API `. + /// + /// The overall extension config discovery service works as follows: + /// + /// #. A filter (:ref:`Downstream Network `, + /// :ref:`Upstream Network `, + /// :ref:`Listener `, + /// :ref:`UDP Session `, + /// or :ref:`HTTP `) + /// contains a (:ref:`ExtensionConfigSource config discovery `) configuration. This configuration + /// includes a :ref:`config_source `, + /// from which the filter configuration will be fetched. + /// #. The client then registers for a resource using the filter name as the ``resource_name``. + /// #. The xDS server sends back the filter's configuration. + /// #. The client stores the configuration that will be used in the next instantiation of the filter chain, + /// i.e., for the next requests. Whenever an updated filter configuration arrives, it will be taken into + /// account in the following instantiation of the filter chain. + /// + /// .. note:: + /// Filters that are configured using ECDS are warmed. For more details see + /// :ref:`ExtensionConfigSource `. + /// /// Return extension configurations. #[derive(Debug, Clone)] pub struct ExtensionConfigDiscoveryServiceClient { @@ -32,7 +56,7 @@ pub mod extension_config_discovery_service_client { } impl ExtensionConfigDiscoveryServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -53,13 +77,13 @@ pub mod extension_config_discovery_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { ExtensionConfigDiscoveryServiceClient::new( @@ -259,6 +283,30 @@ pub mod extension_config_discovery_service_server { tonic::Status, >; } + /// A service that supports dynamic configuration updates for a specific filter. + /// Currently, ECDS is supported for network filters, HTTP filters, UDP session filters, and listener filters. + /// Please check :ref:`Extension Config Discovery Service (ECDS) API `. + /// + /// The overall extension config discovery service works as follows: + /// + /// #. A filter (:ref:`Downstream Network `, + /// :ref:`Upstream Network `, + /// :ref:`Listener `, + /// :ref:`UDP Session `, + /// or :ref:`HTTP `) + /// contains a (:ref:`ExtensionConfigSource config discovery `) configuration. This configuration + /// includes a :ref:`config_source `, + /// from which the filter configuration will be fetched. + /// #. The client then registers for a resource using the filter name as the ``resource_name``. + /// #. The xDS server sends back the filter's configuration. + /// #. The client stores the configuration that will be used in the next instantiation of the filter chain, + /// i.e., for the next requests. Whenever an updated filter configuration arrives, it will be taken into + /// account in the following instantiation of the filter chain. + /// + /// .. note:: + /// Filters that are configured using ECDS are warmed. For more details see + /// :ref:`ExtensionConfigSource `. + /// /// Return extension configurations. #[derive(Debug)] pub struct ExtensionConfigDiscoveryServiceServer { @@ -326,7 +374,7 @@ pub mod extension_config_discovery_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -507,7 +555,9 @@ pub mod extension_config_discovery_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.health.v3.rs b/src/generated/envoy.service.health.v3.rs index 6e9e797..d2d8f0a 100644 --- a/src/generated/envoy.service.health.v3.rs +++ b/src/generated/envoy.service.health.v3.rs @@ -305,7 +305,7 @@ pub mod health_discovery_service_client { } impl HealthDiscoveryServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -326,13 +326,13 @@ pub mod health_discovery_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { HealthDiscoveryServiceClient::new( @@ -615,7 +615,7 @@ pub mod health_discovery_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -735,7 +735,9 @@ pub mod health_discovery_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.listener.v3.rs b/src/generated/envoy.service.listener.v3.rs index 8734065..6054875 100644 --- a/src/generated/envoy.service.listener.v3.rs +++ b/src/generated/envoy.service.listener.v3.rs @@ -34,7 +34,7 @@ pub mod listener_discovery_service_client { } impl ListenerDiscoveryServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -55,13 +55,13 @@ pub mod listener_discovery_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { ListenerDiscoveryServiceClient::new( @@ -331,7 +331,7 @@ pub mod listener_discovery_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -506,7 +506,9 @@ pub mod listener_discovery_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.load_stats.v3.rs b/src/generated/envoy.service.load_stats.v3.rs index 2b6e970..837c7bd 100644 --- a/src/generated/envoy.service.load_stats.v3.rs +++ b/src/generated/envoy.service.load_stats.v3.rs @@ -78,7 +78,7 @@ pub mod load_reporting_service_client { } impl LoadReportingServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -99,13 +99,13 @@ pub mod load_reporting_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { LoadReportingServiceClient::new(InterceptedService::new(inner, interceptor)) @@ -321,7 +321,7 @@ pub mod load_reporting_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -386,7 +386,9 @@ pub mod load_reporting_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.metrics.v3.rs b/src/generated/envoy.service.metrics.v3.rs index e9021c9..df7bd0f 100644 --- a/src/generated/envoy.service.metrics.v3.rs +++ b/src/generated/envoy.service.metrics.v3.rs @@ -74,7 +74,7 @@ pub mod metrics_service_client { } impl MetricsServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -95,13 +95,13 @@ pub mod metrics_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { MetricsServiceClient::new(InterceptedService::new(inner, interceptor)) @@ -262,7 +262,7 @@ pub mod metrics_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -322,7 +322,9 @@ pub mod metrics_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.network_ext_proc.v3.rs b/src/generated/envoy.service.network_ext_proc.v3.rs new file mode 100644 index 0000000..bd24b8f --- /dev/null +++ b/src/generated/envoy.service.network_ext_proc.v3.rs @@ -0,0 +1,533 @@ +// This file is @generated by prost-build. +/// The payload data from network layer +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Data { + /// The raw payload data + #[prost(bytes = "vec", tag = "1")] + pub data: ::prost::alloc::vec::Vec, + /// Indicates whether this is the last data frame in the current direction. + /// The external processor should still respond to this message even + /// if there is no more data expected in this direction. + #[prost(bool, tag = "2")] + pub end_of_stream: bool, +} +impl ::prost::Name for Data { + const NAME: &'static str = "Data"; + const PACKAGE: &'static str = "envoy.service.network_ext_proc.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.service.network_ext_proc.v3.Data".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.service.network_ext_proc.v3.Data".into() + } +} +/// ProcessingRequest contains data sent from Envoy to the external processing server. +/// Each request contains either read data (from client) or write data (to client) +/// along with optional metadata. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ProcessingRequest { + /// ReadData contains the network data intercepted in the request path (client to server). + /// This is sent to the external processor when data arrives from the downstream client. + /// If this is set, write_data should not be set. + #[prost(message, optional, tag = "1")] + pub read_data: ::core::option::Option, + /// WriteData contains the network data intercepted in the response path (server to client). + /// This is sent to the external processor when data arrives from the upstream server. + /// If this is set, read_data should not be set. + #[prost(message, optional, tag = "2")] + pub write_data: ::core::option::Option, + /// Optional metadata associated with the request. + /// This can include connection properties, filter configuration, and any other + /// contextual information that might be useful for processing decisions. + /// + /// The metadata is not automatically propagated from request to response. + /// The external processor must include any needed metadata in its response. + #[prost(message, optional, tag = "3")] + pub metadata: ::core::option::Option< + super::super::super::config::core::v3::Metadata, + >, +} +impl ::prost::Name for ProcessingRequest { + const NAME: &'static str = "ProcessingRequest"; + const PACKAGE: &'static str = "envoy.service.network_ext_proc.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.service.network_ext_proc.v3.ProcessingRequest".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.service.network_ext_proc.v3.ProcessingRequest".into() + } +} +/// ProcessingResponse contains the response from the external processing server to Envoy. +/// Each response corresponds to a ProcessingRequest and indicates how the network +/// traffic should be handled. +/// \[#next-free-field: 6\] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ProcessingResponse { + /// The processed ReadData containing potentially modified data for the request path. + /// This should be sent in response to a ProcessingRequest with read_data, and the + /// previous data in ProcessingRequest will be replaced by the new data in Envoy's data plane. + /// If this is set, write_data should not be set. + #[prost(message, optional, tag = "1")] + pub read_data: ::core::option::Option, + /// The processed WriteData containing potentially modified data for the response path. + /// This should be sent in response to a ProcessingRequest with write_data, and the + /// previous data in ProcessingRequest will be replaced by the new data in Envoy's data plane. + /// If this is set, read_data should not be set. + #[prost(message, optional, tag = "2")] + pub write_data: ::core::option::Option, + /// Indicates whether the data was modified or not. + /// This is mandatory and tells Envoy whether to use the original or modified data. + #[prost(enumeration = "processing_response::DataProcessedStatus", tag = "3")] + pub data_processing_status: i32, + /// Optional: Determines the connection behavior after processing. + /// If not specified, CONTINUE is assumed, and the connection proceeds normally. + /// Use CLOSE or CLOSE_RST to terminate the connection based on processing results. + #[prost(enumeration = "processing_response::ConnectionStatus", tag = "4")] + pub connection_status: i32, + /// Optional metadata associated with the request. + /// This can include connection properties, filter configuration, and any other + /// contextual information that might be useful for processing decisions. + /// + /// The metadata is not automatically propagated from request to response. + /// The external processor must include any needed metadata in its response. + #[prost(message, optional, tag = "5")] + pub dynamic_metadata: ::core::option::Option< + super::super::super::super::google::protobuf::Struct, + >, +} +/// Nested message and enum types in `ProcessingResponse`. +pub mod processing_response { + /// DataProcessedStatus indicates whether the data was modified by the external processor. + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum DataProcessedStatus { + /// The data processed status is unknown. + Unknown = 0, + /// The data remains unchanged. Envoy will use the original data. + /// This is useful when the processor only wants to inspect but not modify the traffic. + Unmodified = 1, + /// The data has been modified. Envoy will use the modified data provided in the response. + /// This allows the processor to transform the network traffic as needed. + Modified = 2, + } + impl DataProcessedStatus { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unknown => "UNKNOWN", + Self::Unmodified => "UNMODIFIED", + Self::Modified => "MODIFIED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "UNKNOWN" => Some(Self::Unknown), + "UNMODIFIED" => Some(Self::Unmodified), + "MODIFIED" => Some(Self::Modified), + _ => None, + } + } + } + /// ConnectionStatus determines what happens to the connection after processing. + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum ConnectionStatus { + /// Continue normal processing of the connection. + /// This is the default behavior and allows traffic to flow normally. + Continue = 0, + /// Close the connection with normal TCP FIN. + /// This allows for clean connection termination with a normal close sequence. + /// Any buffered data will be sent before closing. + Close = 1, + /// Immediately reset the connection with TCP RST. + /// This forcibly terminates the connection without a clean shutdown, + /// discarding any buffered data. Use this for security-critical situations + /// or when immediate termination is required. + CloseRst = 2, + } + impl ConnectionStatus { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Continue => "CONTINUE", + Self::Close => "CLOSE", + Self::CloseRst => "CLOSE_RST", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "CONTINUE" => Some(Self::Continue), + "CLOSE" => Some(Self::Close), + "CLOSE_RST" => Some(Self::CloseRst), + _ => None, + } + } + } +} +impl ::prost::Name for ProcessingResponse { + const NAME: &'static str = "ProcessingResponse"; + const PACKAGE: &'static str = "envoy.service.network_ext_proc.v3"; + fn full_name() -> ::prost::alloc::string::String { + "envoy.service.network_ext_proc.v3.ProcessingResponse".into() + } + fn type_url() -> ::prost::alloc::string::String { + "type.googleapis.com/envoy.service.network_ext_proc.v3.ProcessingResponse".into() + } +} +/// Generated client implementations. +pub mod network_external_processor_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + /// NetworkExternalProcessor service defines the contract between Envoy and + /// external processing servers for L4 network traffic. + #[derive(Debug, Clone)] + pub struct NetworkExternalProcessorClient { + inner: tonic::client::Grpc, + } + impl NetworkExternalProcessorClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> NetworkExternalProcessorClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + NetworkExternalProcessorClient::new( + InterceptedService::new(inner, interceptor), + ) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// Process establishes a bidirectional stream between Envoy and the external + /// processing server. Envoy sends ProcessingRequests containing network data + /// and the server responds with ProcessingResponses containing processing + /// decisions and potentially modified data. + /// + /// The server should handle processing timeout properly to avoid blocking + /// network traffic for extended periods. Any uncaught exceptions will + /// be treated as errors and will terminate the stream. + /// + /// Implementation note: The server should process requests in the order + /// they are received to maintain proper sequencing of network traffic. + pub async fn process( + &mut self, + request: impl tonic::IntoStreamingRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/envoy.service.network_ext_proc.v3.NetworkExternalProcessor/Process", + ); + let mut req = request.into_streaming_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "envoy.service.network_ext_proc.v3.NetworkExternalProcessor", + "Process", + ), + ); + self.inner.streaming(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod network_external_processor_server { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with NetworkExternalProcessorServer. + #[async_trait] + pub trait NetworkExternalProcessor: std::marker::Send + std::marker::Sync + 'static { + /// Server streaming response type for the Process method. + type ProcessStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result, + > + + std::marker::Send + + 'static; + /// Process establishes a bidirectional stream between Envoy and the external + /// processing server. Envoy sends ProcessingRequests containing network data + /// and the server responds with ProcessingResponses containing processing + /// decisions and potentially modified data. + /// + /// The server should handle processing timeout properly to avoid blocking + /// network traffic for extended periods. Any uncaught exceptions will + /// be treated as errors and will terminate the stream. + /// + /// Implementation note: The server should process requests in the order + /// they are received to maintain proper sequencing of network traffic. + async fn process( + &self, + request: tonic::Request>, + ) -> std::result::Result, tonic::Status>; + } + /// NetworkExternalProcessor service defines the contract between Envoy and + /// external processing servers for L4 network traffic. + #[derive(Debug)] + pub struct NetworkExternalProcessorServer { + inner: Arc, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + impl NetworkExternalProcessorServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> + for NetworkExternalProcessorServer + where + T: NetworkExternalProcessor, + B: Body + std::marker::Send + 'static, + B::Error: Into + std::marker::Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + match req.uri().path() { + "/envoy.service.network_ext_proc.v3.NetworkExternalProcessor/Process" => { + #[allow(non_camel_case_types)] + struct ProcessSvc(pub Arc); + impl< + T: NetworkExternalProcessor, + > tonic::server::StreamingService + for ProcessSvc { + type Response = super::ProcessingResponse; + type ResponseStream = T::ProcessStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + tonic::Streaming, + >, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::process(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = ProcessSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + let mut response = http::Response::new( + tonic::body::Body::default(), + ); + let headers = response.headers_mut(); + headers + .insert( + tonic::Status::GRPC_STATUS, + (tonic::Code::Unimplemented as i32).into(), + ); + headers + .insert( + http::header::CONTENT_TYPE, + tonic::metadata::GRPC_CONTENT_TYPE, + ); + Ok(response) + }) + } + } + } + } + impl Clone for NetworkExternalProcessorServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + /// Generated gRPC service name + pub const SERVICE_NAME: &str = "envoy.service.network_ext_proc.v3.NetworkExternalProcessor"; + impl tonic::server::NamedService for NetworkExternalProcessorServer { + const NAME: &'static str = SERVICE_NAME; + } +} diff --git a/src/generated/envoy.service.network_ext_proc.v3.serde.rs b/src/generated/envoy.service.network_ext_proc.v3.serde.rs new file mode 100644 index 0000000..65d0a9a --- /dev/null +++ b/src/generated/envoy.service.network_ext_proc.v3.serde.rs @@ -0,0 +1,556 @@ +impl serde::Serialize for Data { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.data.is_empty() { + len += 1; + } + if self.end_of_stream { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.service.network_ext_proc.v3.Data", len)?; + if !self.data.is_empty() { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("data", pbjson::private::base64::encode(&self.data).as_str())?; + } + if self.end_of_stream { + struct_ser.serialize_field("end_of_stream", &self.end_of_stream)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for Data { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "data", + "end_of_stream", + "endOfStream", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Data, + EndOfStream, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "data" => Ok(GeneratedField::Data), + "endOfStream" | "end_of_stream" => Ok(GeneratedField::EndOfStream), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = Data; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.service.network_ext_proc.v3.Data") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut data__ = None; + let mut end_of_stream__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Data => { + if data__.is_some() { + return Err(serde::de::Error::duplicate_field("data")); + } + data__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + GeneratedField::EndOfStream => { + if end_of_stream__.is_some() { + return Err(serde::de::Error::duplicate_field("endOfStream")); + } + end_of_stream__ = Some(map_.next_value()?); + } + } + } + Ok(Data { + data: data__.unwrap_or_default(), + end_of_stream: end_of_stream__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.service.network_ext_proc.v3.Data", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for ProcessingRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.read_data.is_some() { + len += 1; + } + if self.write_data.is_some() { + len += 1; + } + if self.metadata.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.service.network_ext_proc.v3.ProcessingRequest", len)?; + if let Some(v) = self.read_data.as_ref() { + struct_ser.serialize_field("read_data", v)?; + } + if let Some(v) = self.write_data.as_ref() { + struct_ser.serialize_field("write_data", v)?; + } + if let Some(v) = self.metadata.as_ref() { + struct_ser.serialize_field("metadata", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ProcessingRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "read_data", + "readData", + "write_data", + "writeData", + "metadata", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ReadData, + WriteData, + Metadata, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "readData" | "read_data" => Ok(GeneratedField::ReadData), + "writeData" | "write_data" => Ok(GeneratedField::WriteData), + "metadata" => Ok(GeneratedField::Metadata), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ProcessingRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.service.network_ext_proc.v3.ProcessingRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut read_data__ = None; + let mut write_data__ = None; + let mut metadata__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ReadData => { + if read_data__.is_some() { + return Err(serde::de::Error::duplicate_field("readData")); + } + read_data__ = map_.next_value()?; + } + GeneratedField::WriteData => { + if write_data__.is_some() { + return Err(serde::de::Error::duplicate_field("writeData")); + } + write_data__ = map_.next_value()?; + } + GeneratedField::Metadata => { + if metadata__.is_some() { + return Err(serde::de::Error::duplicate_field("metadata")); + } + metadata__ = map_.next_value()?; + } + } + } + Ok(ProcessingRequest { + read_data: read_data__, + write_data: write_data__, + metadata: metadata__, + }) + } + } + deserializer.deserialize_struct("envoy.service.network_ext_proc.v3.ProcessingRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for ProcessingResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.read_data.is_some() { + len += 1; + } + if self.write_data.is_some() { + len += 1; + } + if self.data_processing_status != 0 { + len += 1; + } + if self.connection_status != 0 { + len += 1; + } + if self.dynamic_metadata.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.service.network_ext_proc.v3.ProcessingResponse", len)?; + if let Some(v) = self.read_data.as_ref() { + struct_ser.serialize_field("read_data", v)?; + } + if let Some(v) = self.write_data.as_ref() { + struct_ser.serialize_field("write_data", v)?; + } + if self.data_processing_status != 0 { + let v = processing_response::DataProcessedStatus::try_from(self.data_processing_status) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", self.data_processing_status)))?; + struct_ser.serialize_field("data_processing_status", &v)?; + } + if self.connection_status != 0 { + let v = processing_response::ConnectionStatus::try_from(self.connection_status) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", self.connection_status)))?; + struct_ser.serialize_field("connection_status", &v)?; + } + if let Some(v) = self.dynamic_metadata.as_ref() { + struct_ser.serialize_field("dynamic_metadata", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ProcessingResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "read_data", + "readData", + "write_data", + "writeData", + "data_processing_status", + "dataProcessingStatus", + "connection_status", + "connectionStatus", + "dynamic_metadata", + "dynamicMetadata", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ReadData, + WriteData, + DataProcessingStatus, + ConnectionStatus, + DynamicMetadata, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "readData" | "read_data" => Ok(GeneratedField::ReadData), + "writeData" | "write_data" => Ok(GeneratedField::WriteData), + "dataProcessingStatus" | "data_processing_status" => Ok(GeneratedField::DataProcessingStatus), + "connectionStatus" | "connection_status" => Ok(GeneratedField::ConnectionStatus), + "dynamicMetadata" | "dynamic_metadata" => Ok(GeneratedField::DynamicMetadata), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ProcessingResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.service.network_ext_proc.v3.ProcessingResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut read_data__ = None; + let mut write_data__ = None; + let mut data_processing_status__ = None; + let mut connection_status__ = None; + let mut dynamic_metadata__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ReadData => { + if read_data__.is_some() { + return Err(serde::de::Error::duplicate_field("readData")); + } + read_data__ = map_.next_value()?; + } + GeneratedField::WriteData => { + if write_data__.is_some() { + return Err(serde::de::Error::duplicate_field("writeData")); + } + write_data__ = map_.next_value()?; + } + GeneratedField::DataProcessingStatus => { + if data_processing_status__.is_some() { + return Err(serde::de::Error::duplicate_field("dataProcessingStatus")); + } + data_processing_status__ = Some(map_.next_value::()? as i32); + } + GeneratedField::ConnectionStatus => { + if connection_status__.is_some() { + return Err(serde::de::Error::duplicate_field("connectionStatus")); + } + connection_status__ = Some(map_.next_value::()? as i32); + } + GeneratedField::DynamicMetadata => { + if dynamic_metadata__.is_some() { + return Err(serde::de::Error::duplicate_field("dynamicMetadata")); + } + dynamic_metadata__ = map_.next_value()?; + } + } + } + Ok(ProcessingResponse { + read_data: read_data__, + write_data: write_data__, + data_processing_status: data_processing_status__.unwrap_or_default(), + connection_status: connection_status__.unwrap_or_default(), + dynamic_metadata: dynamic_metadata__, + }) + } + } + deserializer.deserialize_struct("envoy.service.network_ext_proc.v3.ProcessingResponse", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for processing_response::ConnectionStatus { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + let variant = match self { + Self::Continue => "CONTINUE", + Self::Close => "CLOSE", + Self::CloseRst => "CLOSE_RST", + }; + serializer.serialize_str(variant) + } +} +impl<'de> serde::Deserialize<'de> for processing_response::ConnectionStatus { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "CONTINUE", + "CLOSE", + "CLOSE_RST", + ]; + + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = processing_response::ConnectionStatus; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + fn visit_i64(self, v: i64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) + }) + } + + fn visit_u64(self, v: u64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) + }) + } + + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "CONTINUE" => Ok(processing_response::ConnectionStatus::Continue), + "CLOSE" => Ok(processing_response::ConnectionStatus::Close), + "CLOSE_RST" => Ok(processing_response::ConnectionStatus::CloseRst), + _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), + } + } + } + deserializer.deserialize_any(GeneratedVisitor) + } +} +impl serde::Serialize for processing_response::DataProcessedStatus { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + let variant = match self { + Self::Unknown => "UNKNOWN", + Self::Unmodified => "UNMODIFIED", + Self::Modified => "MODIFIED", + }; + serializer.serialize_str(variant) + } +} +impl<'de> serde::Deserialize<'de> for processing_response::DataProcessedStatus { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "UNKNOWN", + "UNMODIFIED", + "MODIFIED", + ]; + + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = processing_response::DataProcessedStatus; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + fn visit_i64(self, v: i64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) + }) + } + + fn visit_u64(self, v: u64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) + }) + } + + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "UNKNOWN" => Ok(processing_response::DataProcessedStatus::Unknown), + "UNMODIFIED" => Ok(processing_response::DataProcessedStatus::Unmodified), + "MODIFIED" => Ok(processing_response::DataProcessedStatus::Modified), + _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), + } + } + } + deserializer.deserialize_any(GeneratedVisitor) + } +} diff --git a/src/generated/envoy.service.rate_limit_quota.v3.rs b/src/generated/envoy.service.rate_limit_quota.v3.rs index d8a5ceb..21ae607 100644 --- a/src/generated/envoy.service.rate_limit_quota.v3.rs +++ b/src/generated/envoy.service.rate_limit_quota.v3.rs @@ -310,7 +310,7 @@ pub mod rate_limit_quota_service_client { } impl RateLimitQuotaServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -331,13 +331,13 @@ pub mod rate_limit_quota_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { RateLimitQuotaServiceClient::new(InterceptedService::new(inner, interceptor)) @@ -504,7 +504,7 @@ pub mod rate_limit_quota_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -571,7 +571,9 @@ pub mod rate_limit_quota_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.ratelimit.v3.rs b/src/generated/envoy.service.ratelimit.v3.rs index 9effd0a..1503649 100644 --- a/src/generated/envoy.service.ratelimit.v3.rs +++ b/src/generated/envoy.service.ratelimit.v3.rs @@ -21,6 +21,8 @@ pub struct RateLimitRequest { >, /// Rate limit requests can optionally specify the number of hits a request adds to the matched /// limit. If the value is not set in the message, a request increases the matched limit by 1. + /// This value can be overridden by setting filter state value ``envoy.ratelimit.hits_addend`` + /// to the desired number. Invalid number (< 0) or number will be ignored. #[prost(uint32, tag = "3")] pub hits_addend: u32, } @@ -127,6 +129,8 @@ pub mod rate_limit_response { Hour = 3, /// The time unit representing a day. Day = 4, + /// The time unit representing a week. + Week = 7, /// The time unit representing a month. Month = 5, /// The time unit representing a year. @@ -144,6 +148,7 @@ pub mod rate_limit_response { Self::Minute => "MINUTE", Self::Hour => "HOUR", Self::Day => "DAY", + Self::Week => "WEEK", Self::Month => "MONTH", Self::Year => "YEAR", } @@ -156,6 +161,7 @@ pub mod rate_limit_response { "MINUTE" => Some(Self::Minute), "HOUR" => Some(Self::Hour), "DAY" => Some(Self::Day), + "WEEK" => Some(Self::Week), "MONTH" => Some(Self::Month), "YEAR" => Some(Self::Year), _ => None, @@ -348,7 +354,7 @@ pub mod rate_limit_service_client { } impl RateLimitServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -369,13 +375,13 @@ pub mod rate_limit_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { RateLimitServiceClient::new(InterceptedService::new(inner, interceptor)) @@ -530,7 +536,7 @@ pub mod rate_limit_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -589,7 +595,9 @@ pub mod rate_limit_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.ratelimit.v3.serde.rs b/src/generated/envoy.service.ratelimit.v3.serde.rs index 341efd2..0c49707 100644 --- a/src/generated/envoy.service.ratelimit.v3.serde.rs +++ b/src/generated/envoy.service.ratelimit.v3.serde.rs @@ -845,6 +845,7 @@ impl serde::Serialize for rate_limit_response::rate_limit::Unit { Self::Minute => "MINUTE", Self::Hour => "HOUR", Self::Day => "DAY", + Self::Week => "WEEK", Self::Month => "MONTH", Self::Year => "YEAR", }; @@ -863,6 +864,7 @@ impl<'de> serde::Deserialize<'de> for rate_limit_response::rate_limit::Unit { "MINUTE", "HOUR", "DAY", + "WEEK", "MONTH", "YEAR", ]; @@ -910,6 +912,7 @@ impl<'de> serde::Deserialize<'de> for rate_limit_response::rate_limit::Unit { "MINUTE" => Ok(rate_limit_response::rate_limit::Unit::Minute), "HOUR" => Ok(rate_limit_response::rate_limit::Unit::Hour), "DAY" => Ok(rate_limit_response::rate_limit::Unit::Day), + "WEEK" => Ok(rate_limit_response::rate_limit::Unit::Week), "MONTH" => Ok(rate_limit_response::rate_limit::Unit::Month), "YEAR" => Ok(rate_limit_response::rate_limit::Unit::Year), _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), diff --git a/src/generated/envoy.service.trace.v3.rs b/src/generated/envoy.service.redis_auth.v3.rs similarity index 64% rename from src/generated/envoy.service.trace.v3.rs rename to src/generated/envoy.service.redis_auth.v3.rs index db0a64e..23023e8 100644 --- a/src/generated/envoy.service.trace.v3.rs +++ b/src/generated/envoy.service.redis_auth.v3.rs @@ -1,63 +1,53 @@ // This file is @generated by prost-build. -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct StreamTracesResponse {} -impl ::prost::Name for StreamTracesResponse { - const NAME: &'static str = "StreamTracesResponse"; - const PACKAGE: &'static str = "envoy.service.trace.v3"; +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RedisProxyExternalAuthRequest { + /// Username, if applicable. Otherwise, empty. + #[prost(string, tag = "1")] + pub username: ::prost::alloc::string::String, + /// Password sent with the AUTH command. + #[prost(string, tag = "2")] + pub password: ::prost::alloc::string::String, +} +impl ::prost::Name for RedisProxyExternalAuthRequest { + const NAME: &'static str = "RedisProxyExternalAuthRequest"; + const PACKAGE: &'static str = "envoy.service.redis_auth.v3"; fn full_name() -> ::prost::alloc::string::String { - "envoy.service.trace.v3.StreamTracesResponse".into() + "envoy.service.redis_auth.v3.RedisProxyExternalAuthRequest".into() } fn type_url() -> ::prost::alloc::string::String { - "type.googleapis.com/envoy.service.trace.v3.StreamTracesResponse".into() + "type.googleapis.com/envoy.service.redis_auth.v3.RedisProxyExternalAuthRequest" + .into() } } #[derive(Clone, PartialEq, ::prost::Message)] -pub struct StreamTracesMessage { - /// Identifier data effectively is a structured metadata. - /// As a performance optimization this will only be sent in the first message - /// on the stream. +pub struct RedisProxyExternalAuthResponse { + /// Status of the authentication check. #[prost(message, optional, tag = "1")] - pub identifier: ::core::option::Option, - /// A list of Span entries - #[prost(message, repeated, tag = "2")] - pub spans: ::prost::alloc::vec::Vec< - super::super::super::super::opencensus::proto::trace::v1::Span, + pub status: ::core::option::Option, + /// Optional expiration time for the authentication. + /// If set, the authentication will be valid until this time. + /// If not set, the authentication will be valid indefinitely. + #[prost(message, optional, tag = "2")] + pub expiration: ::core::option::Option< + super::super::super::super::google::protobuf::Timestamp, >, + /// Optional message to be sent back to the client. + #[prost(string, tag = "3")] + pub message: ::prost::alloc::string::String, } -/// Nested message and enum types in `StreamTracesMessage`. -pub mod stream_traces_message { - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct Identifier { - /// The node sending the access log messages over the stream. - #[prost(message, optional, tag = "1")] - pub node: ::core::option::Option< - super::super::super::super::config::core::v3::Node, - >, - } - impl ::prost::Name for Identifier { - const NAME: &'static str = "Identifier"; - const PACKAGE: &'static str = "envoy.service.trace.v3"; - fn full_name() -> ::prost::alloc::string::String { - "envoy.service.trace.v3.StreamTracesMessage.Identifier".into() - } - fn type_url() -> ::prost::alloc::string::String { - "type.googleapis.com/envoy.service.trace.v3.StreamTracesMessage.Identifier" - .into() - } - } -} -impl ::prost::Name for StreamTracesMessage { - const NAME: &'static str = "StreamTracesMessage"; - const PACKAGE: &'static str = "envoy.service.trace.v3"; +impl ::prost::Name for RedisProxyExternalAuthResponse { + const NAME: &'static str = "RedisProxyExternalAuthResponse"; + const PACKAGE: &'static str = "envoy.service.redis_auth.v3"; fn full_name() -> ::prost::alloc::string::String { - "envoy.service.trace.v3.StreamTracesMessage".into() + "envoy.service.redis_auth.v3.RedisProxyExternalAuthResponse".into() } fn type_url() -> ::prost::alloc::string::String { - "type.googleapis.com/envoy.service.trace.v3.StreamTracesMessage".into() + "type.googleapis.com/envoy.service.redis_auth.v3.RedisProxyExternalAuthResponse" + .into() } } /// Generated client implementations. -pub mod trace_service_client { +pub mod redis_proxy_external_auth_client { #![allow( unused_variables, dead_code, @@ -67,15 +57,14 @@ pub mod trace_service_client { )] use tonic::codegen::*; use tonic::codegen::http::Uri; - /// Service for streaming traces to server that consumes the trace data. It - /// uses OpenCensus data model as a standard to represent trace information. + /// A generic interface for performing external password authentication on incoming AUTH commands. #[derive(Debug, Clone)] - pub struct TraceServiceClient { + pub struct RedisProxyExternalAuthClient { inner: tonic::client::Grpc, } - impl TraceServiceClient + impl RedisProxyExternalAuthClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -91,21 +80,23 @@ pub mod trace_service_client { pub fn with_interceptor( inner: T, interceptor: F, - ) -> TraceServiceClient> + ) -> RedisProxyExternalAuthClient> where F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { - TraceServiceClient::new(InterceptedService::new(inner, interceptor)) + RedisProxyExternalAuthClient::new( + InterceptedService::new(inner, interceptor), + ) } /// Compress requests with the given encoding. /// @@ -138,16 +129,13 @@ pub mod trace_service_client { self.inner = self.inner.max_encoding_message_size(limit); self } - /// Envoy will connect and send StreamTracesMessage messages forever. It does - /// not expect any response to be sent as nothing would be done in the case - /// of failure. - pub async fn stream_traces( + /// Performs authentication check based on the data sent with the AUTH request. + /// Returns either an OK status or an error status. + pub async fn authenticate( &mut self, - request: impl tonic::IntoStreamingRequest< - Message = super::StreamTracesMessage, - >, + request: impl tonic::IntoRequest, ) -> std::result::Result< - tonic::Response, + tonic::Response, tonic::Status, > { self.inner @@ -160,22 +148,22 @@ pub mod trace_service_client { })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( - "/envoy.service.trace.v3.TraceService/StreamTraces", + "/envoy.service.redis_auth.v3.RedisProxyExternalAuth/Authenticate", ); - let mut req = request.into_streaming_request(); + let mut req = request.into_request(); req.extensions_mut() .insert( GrpcMethod::new( - "envoy.service.trace.v3.TraceService", - "StreamTraces", + "envoy.service.redis_auth.v3.RedisProxyExternalAuth", + "Authenticate", ), ); - self.inner.client_streaming(req, path, codec).await + self.inner.unary(req, path, codec).await } } } /// Generated server implementations. -pub mod trace_service_server { +pub mod redis_proxy_external_auth_server { #![allow( unused_variables, dead_code, @@ -184,31 +172,29 @@ pub mod trace_service_server { clippy::let_unit_value, )] use tonic::codegen::*; - /// Generated trait containing gRPC methods that should be implemented for use with TraceServiceServer. + /// Generated trait containing gRPC methods that should be implemented for use with RedisProxyExternalAuthServer. #[async_trait] - pub trait TraceService: std::marker::Send + std::marker::Sync + 'static { - /// Envoy will connect and send StreamTracesMessage messages forever. It does - /// not expect any response to be sent as nothing would be done in the case - /// of failure. - async fn stream_traces( + pub trait RedisProxyExternalAuth: std::marker::Send + std::marker::Sync + 'static { + /// Performs authentication check based on the data sent with the AUTH request. + /// Returns either an OK status or an error status. + async fn authenticate( &self, - request: tonic::Request>, + request: tonic::Request, ) -> std::result::Result< - tonic::Response, + tonic::Response, tonic::Status, >; } - /// Service for streaming traces to server that consumes the trace data. It - /// uses OpenCensus data model as a standard to represent trace information. + /// A generic interface for performing external password authentication on incoming AUTH commands. #[derive(Debug)] - pub struct TraceServiceServer { + pub struct RedisProxyExternalAuthServer { inner: Arc, accept_compression_encodings: EnabledCompressionEncodings, send_compression_encodings: EnabledCompressionEncodings, max_decoding_message_size: Option, max_encoding_message_size: Option, } - impl TraceServiceServer { + impl RedisProxyExternalAuthServer { pub fn new(inner: T) -> Self { Self::from_arc(Arc::new(inner)) } @@ -259,13 +245,14 @@ pub mod trace_service_server { self } } - impl tonic::codegen::Service> for TraceServiceServer + impl tonic::codegen::Service> + for RedisProxyExternalAuthServer where - T: TraceService, + T: RedisProxyExternalAuth, B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -276,27 +263,26 @@ pub mod trace_service_server { } fn call(&mut self, req: http::Request) -> Self::Future { match req.uri().path() { - "/envoy.service.trace.v3.TraceService/StreamTraces" => { + "/envoy.service.redis_auth.v3.RedisProxyExternalAuth/Authenticate" => { #[allow(non_camel_case_types)] - struct StreamTracesSvc(pub Arc); + struct AuthenticateSvc(pub Arc); impl< - T: TraceService, - > tonic::server::ClientStreamingService - for StreamTracesSvc { - type Response = super::StreamTracesResponse; + T: RedisProxyExternalAuth, + > tonic::server::UnaryService + for AuthenticateSvc { + type Response = super::RedisProxyExternalAuthResponse; type Future = BoxFuture< tonic::Response, tonic::Status, >; fn call( &mut self, - request: tonic::Request< - tonic::Streaming, - >, + request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::stream_traces(&inner, request).await + ::authenticate(&inner, request) + .await }; Box::pin(fut) } @@ -307,7 +293,7 @@ pub mod trace_service_server { let max_encoding_message_size = self.max_encoding_message_size; let inner = self.inner.clone(); let fut = async move { - let method = StreamTracesSvc(inner); + let method = AuthenticateSvc(inner); let codec = tonic::codec::ProstCodec::default(); let mut grpc = tonic::server::Grpc::new(codec) .apply_compression_config( @@ -318,14 +304,16 @@ pub mod trace_service_server { max_decoding_message_size, max_encoding_message_size, ); - let res = grpc.client_streaming(method, req).await; + let res = grpc.unary(method, req).await; Ok(res) }; Box::pin(fut) } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( @@ -343,7 +331,7 @@ pub mod trace_service_server { } } } - impl Clone for TraceServiceServer { + impl Clone for RedisProxyExternalAuthServer { fn clone(&self) -> Self { let inner = self.inner.clone(); Self { @@ -356,8 +344,8 @@ pub mod trace_service_server { } } /// Generated gRPC service name - pub const SERVICE_NAME: &str = "envoy.service.trace.v3.TraceService"; - impl tonic::server::NamedService for TraceServiceServer { + pub const SERVICE_NAME: &str = "envoy.service.redis_auth.v3.RedisProxyExternalAuth"; + impl tonic::server::NamedService for RedisProxyExternalAuthServer { const NAME: &'static str = SERVICE_NAME; } } diff --git a/src/generated/envoy.service.redis_auth.v3.serde.rs b/src/generated/envoy.service.redis_auth.v3.serde.rs new file mode 100644 index 0000000..4f78323 --- /dev/null +++ b/src/generated/envoy.service.redis_auth.v3.serde.rs @@ -0,0 +1,233 @@ +impl serde::Serialize for RedisProxyExternalAuthRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.username.is_empty() { + len += 1; + } + if !self.password.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.service.redis_auth.v3.RedisProxyExternalAuthRequest", len)?; + if !self.username.is_empty() { + struct_ser.serialize_field("username", &self.username)?; + } + if !self.password.is_empty() { + struct_ser.serialize_field("password", &self.password)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for RedisProxyExternalAuthRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "username", + "password", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Username, + Password, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "username" => Ok(GeneratedField::Username), + "password" => Ok(GeneratedField::Password), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = RedisProxyExternalAuthRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.service.redis_auth.v3.RedisProxyExternalAuthRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut username__ = None; + let mut password__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Username => { + if username__.is_some() { + return Err(serde::de::Error::duplicate_field("username")); + } + username__ = Some(map_.next_value()?); + } + GeneratedField::Password => { + if password__.is_some() { + return Err(serde::de::Error::duplicate_field("password")); + } + password__ = Some(map_.next_value()?); + } + } + } + Ok(RedisProxyExternalAuthRequest { + username: username__.unwrap_or_default(), + password: password__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.service.redis_auth.v3.RedisProxyExternalAuthRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for RedisProxyExternalAuthResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.status.is_some() { + len += 1; + } + if self.expiration.is_some() { + len += 1; + } + if !self.message.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("envoy.service.redis_auth.v3.RedisProxyExternalAuthResponse", len)?; + if let Some(v) = self.status.as_ref() { + struct_ser.serialize_field("status", v)?; + } + if let Some(v) = self.expiration.as_ref() { + struct_ser.serialize_field("expiration", v)?; + } + if !self.message.is_empty() { + struct_ser.serialize_field("message", &self.message)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for RedisProxyExternalAuthResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "status", + "expiration", + "message", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Status, + Expiration, + Message, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "status" => Ok(GeneratedField::Status), + "expiration" => Ok(GeneratedField::Expiration), + "message" => Ok(GeneratedField::Message), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = RedisProxyExternalAuthResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct envoy.service.redis_auth.v3.RedisProxyExternalAuthResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut status__ = None; + let mut expiration__ = None; + let mut message__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Status => { + if status__.is_some() { + return Err(serde::de::Error::duplicate_field("status")); + } + status__ = map_.next_value()?; + } + GeneratedField::Expiration => { + if expiration__.is_some() { + return Err(serde::de::Error::duplicate_field("expiration")); + } + expiration__ = map_.next_value()?; + } + GeneratedField::Message => { + if message__.is_some() { + return Err(serde::de::Error::duplicate_field("message")); + } + message__ = Some(map_.next_value()?); + } + } + } + Ok(RedisProxyExternalAuthResponse { + status: status__, + expiration: expiration__, + message: message__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("envoy.service.redis_auth.v3.RedisProxyExternalAuthResponse", FIELDS, GeneratedVisitor) + } +} diff --git a/src/generated/envoy.service.route.v3.rs b/src/generated/envoy.service.route.v3.rs index 841a183..ef22be1 100644 --- a/src/generated/envoy.service.route.v3.rs +++ b/src/generated/envoy.service.route.v3.rs @@ -35,7 +35,7 @@ pub mod route_discovery_service_client { } impl RouteDiscoveryServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -56,13 +56,13 @@ pub mod route_discovery_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { RouteDiscoveryServiceClient::new(InterceptedService::new(inner, interceptor)) @@ -228,7 +228,7 @@ pub mod virtual_host_discovery_service_client { } impl VirtualHostDiscoveryServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -249,13 +249,13 @@ pub mod virtual_host_discovery_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { VirtualHostDiscoveryServiceClient::new( @@ -460,7 +460,7 @@ pub mod route_discovery_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -626,7 +626,9 @@ pub mod route_discovery_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( @@ -772,7 +774,7 @@ pub mod virtual_host_discovery_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -842,7 +844,9 @@ pub mod virtual_host_discovery_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( @@ -916,7 +920,7 @@ pub mod scoped_routes_discovery_service_client { } impl ScopedRoutesDiscoveryServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -937,13 +941,13 @@ pub mod scoped_routes_discovery_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { ScopedRoutesDiscoveryServiceClient::new( @@ -1216,7 +1220,7 @@ pub mod scoped_routes_discovery_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -1397,7 +1401,9 @@ pub mod scoped_routes_discovery_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.runtime.v3.rs b/src/generated/envoy.service.runtime.v3.rs index bf3b225..d236cf2 100644 --- a/src/generated/envoy.service.runtime.v3.rs +++ b/src/generated/envoy.service.runtime.v3.rs @@ -53,7 +53,7 @@ pub mod runtime_discovery_service_client { } impl RuntimeDiscoveryServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -74,13 +74,13 @@ pub mod runtime_discovery_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { RuntimeDiscoveryServiceClient::new( @@ -347,7 +347,7 @@ pub mod runtime_discovery_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -522,7 +522,9 @@ pub mod runtime_discovery_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.secret.v3.rs b/src/generated/envoy.service.secret.v3.rs index 8b5623d..b3218ef 100644 --- a/src/generated/envoy.service.secret.v3.rs +++ b/src/generated/envoy.service.secret.v3.rs @@ -30,7 +30,7 @@ pub mod secret_discovery_service_client { } impl SecretDiscoveryServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -51,13 +51,13 @@ pub mod secret_discovery_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { SecretDiscoveryServiceClient::new( @@ -323,7 +323,7 @@ pub mod secret_discovery_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -498,7 +498,9 @@ pub mod secret_discovery_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.status.v3.rs b/src/generated/envoy.service.status.v3.rs index cee0eba..f8252b5 100644 --- a/src/generated/envoy.service.status.v3.rs +++ b/src/generated/envoy.service.status.v3.rs @@ -248,6 +248,10 @@ pub enum ClientConfigStatus { /// config dump is not the NACKed version, but the most recent accepted one. If /// no config is accepted yet, the attached config dump will be empty. ClientNacked = 3, + /// Client received an error from the control plane. The attached config + /// dump is the most recent accepted one. If no config is accepted yet, + /// the attached config dump will be empty. + ClientReceivedError = 4, } impl ClientConfigStatus { /// String value of the enum field names used in the ProtoBuf definition. @@ -260,6 +264,7 @@ impl ClientConfigStatus { Self::ClientRequested => "CLIENT_REQUESTED", Self::ClientAcked => "CLIENT_ACKED", Self::ClientNacked => "CLIENT_NACKED", + Self::ClientReceivedError => "CLIENT_RECEIVED_ERROR", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -269,6 +274,7 @@ impl ClientConfigStatus { "CLIENT_REQUESTED" => Some(Self::ClientRequested), "CLIENT_ACKED" => Some(Self::ClientAcked), "CLIENT_NACKED" => Some(Self::ClientNacked), + "CLIENT_RECEIVED_ERROR" => Some(Self::ClientReceivedError), _ => None, } } @@ -293,7 +299,7 @@ pub mod client_status_discovery_service_client { } impl ClientStatusDiscoveryServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -314,13 +320,13 @@ pub mod client_status_discovery_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { ClientStatusDiscoveryServiceClient::new( @@ -523,7 +529,7 @@ pub mod client_status_discovery_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -641,7 +647,9 @@ pub mod client_status_discovery_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.status.v3.serde.rs b/src/generated/envoy.service.status.v3.serde.rs index a98bc39..daa1086 100644 --- a/src/generated/envoy.service.status.v3.serde.rs +++ b/src/generated/envoy.service.status.v3.serde.rs @@ -393,6 +393,7 @@ impl serde::Serialize for ClientConfigStatus { Self::ClientRequested => "CLIENT_REQUESTED", Self::ClientAcked => "CLIENT_ACKED", Self::ClientNacked => "CLIENT_NACKED", + Self::ClientReceivedError => "CLIENT_RECEIVED_ERROR", }; serializer.serialize_str(variant) } @@ -408,6 +409,7 @@ impl<'de> serde::Deserialize<'de> for ClientConfigStatus { "CLIENT_REQUESTED", "CLIENT_ACKED", "CLIENT_NACKED", + "CLIENT_RECEIVED_ERROR", ]; struct GeneratedVisitor; @@ -452,6 +454,7 @@ impl<'de> serde::Deserialize<'de> for ClientConfigStatus { "CLIENT_REQUESTED" => Ok(ClientConfigStatus::ClientRequested), "CLIENT_ACKED" => Ok(ClientConfigStatus::ClientAcked), "CLIENT_NACKED" => Ok(ClientConfigStatus::ClientNacked), + "CLIENT_RECEIVED_ERROR" => Ok(ClientConfigStatus::ClientReceivedError), _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), } } diff --git a/src/generated/envoy.service.tap.v3.rs b/src/generated/envoy.service.tap.v3.rs index 5a7a4de..844aaea 100644 --- a/src/generated/envoy.service.tap.v3.rs +++ b/src/generated/envoy.service.tap.v3.rs @@ -83,7 +83,7 @@ pub mod tap_sink_service_client { } impl TapSinkServiceClient where - T: tonic::client::GrpcService, + T: tonic::client::GrpcService, T::Error: Into, T::ResponseBody: Body + std::marker::Send + 'static, ::Error: Into + std::marker::Send, @@ -104,13 +104,13 @@ pub mod tap_sink_service_client { F: tonic::service::Interceptor, T::ResponseBody: Default, T: tonic::codegen::Service< - http::Request, + http::Request, Response = http::Response< - >::ResponseBody, + >::ResponseBody, >, >, , + http::Request, >>::Error: Into + std::marker::Send + std::marker::Sync, { TapSinkServiceClient::new(InterceptedService::new(inner, interceptor)) @@ -268,7 +268,7 @@ pub mod tap_sink_service_server { B: Body + std::marker::Send + 'static, B::Error: Into + std::marker::Send + 'static, { - type Response = http::Response; + type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; fn poll_ready( @@ -328,7 +328,9 @@ pub mod tap_sink_service_server { } _ => { Box::pin(async move { - let mut response = http::Response::new(empty_body()); + let mut response = http::Response::new( + tonic::body::Body::default(), + ); let headers = response.headers_mut(); headers .insert( diff --git a/src/generated/envoy.service.trace.v3.serde.rs b/src/generated/envoy.service.trace.v3.serde.rs deleted file mode 100644 index 81b83a4..0000000 --- a/src/generated/envoy.service.trace.v3.serde.rs +++ /dev/null @@ -1,270 +0,0 @@ -impl serde::Serialize for StreamTracesMessage { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.identifier.is_some() { - len += 1; - } - if !self.spans.is_empty() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("envoy.service.trace.v3.StreamTracesMessage", len)?; - if let Some(v) = self.identifier.as_ref() { - struct_ser.serialize_field("identifier", v)?; - } - if !self.spans.is_empty() { - struct_ser.serialize_field("spans", &self.spans)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for StreamTracesMessage { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "identifier", - "spans", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Identifier, - Spans, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "identifier" => Ok(GeneratedField::Identifier), - "spans" => Ok(GeneratedField::Spans), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = StreamTracesMessage; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct envoy.service.trace.v3.StreamTracesMessage") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut identifier__ = None; - let mut spans__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Identifier => { - if identifier__.is_some() { - return Err(serde::de::Error::duplicate_field("identifier")); - } - identifier__ = map_.next_value()?; - } - GeneratedField::Spans => { - if spans__.is_some() { - return Err(serde::de::Error::duplicate_field("spans")); - } - spans__ = Some(map_.next_value()?); - } - } - } - Ok(StreamTracesMessage { - identifier: identifier__, - spans: spans__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("envoy.service.trace.v3.StreamTracesMessage", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for stream_traces_message::Identifier { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.node.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("envoy.service.trace.v3.StreamTracesMessage.Identifier", len)?; - if let Some(v) = self.node.as_ref() { - struct_ser.serialize_field("node", v)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for stream_traces_message::Identifier { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "node", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Node, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "node" => Ok(GeneratedField::Node), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = stream_traces_message::Identifier; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct envoy.service.trace.v3.StreamTracesMessage.Identifier") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut node__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Node => { - if node__.is_some() { - return Err(serde::de::Error::duplicate_field("node")); - } - node__ = map_.next_value()?; - } - } - } - Ok(stream_traces_message::Identifier { - node: node__, - }) - } - } - deserializer.deserialize_struct("envoy.service.trace.v3.StreamTracesMessage.Identifier", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for StreamTracesResponse { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let len = 0; - let struct_ser = serializer.serialize_struct("envoy.service.trace.v3.StreamTracesResponse", len)?; - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for StreamTracesResponse { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - Err(serde::de::Error::unknown_field(value, FIELDS)) - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = StreamTracesResponse; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct envoy.service.trace.v3.StreamTracesResponse") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - while map_.next_key::()?.is_some() { - let _ = map_.next_value::()?; - } - Ok(StreamTracesResponse { - }) - } - } - deserializer.deserialize_struct("envoy.service.trace.v3.StreamTracesResponse", FIELDS, GeneratedVisitor) - } -} diff --git a/src/generated/google.api.expr.v1alpha1.rs b/src/generated/google.api.expr.v1alpha1.rs index 6948c05..da07100 100644 --- a/src/generated/google.api.expr.v1alpha1.rs +++ b/src/generated/google.api.expr.v1alpha1.rs @@ -26,14 +26,16 @@ impl ::prost::Name for ParsedExpr { /// operators with the exception of the '.' operator are modelled as function /// calls. This makes it easy to represent new operators into the existing AST. /// -/// All references within expressions must resolve to a [Decl][google.api.expr.v1alpha1.Decl] provided at -/// type-check for an expression to be valid. A reference may either be a bare -/// identifier `name` or a qualified identifier `google.api.name`. References -/// may either refer to a value or a function declaration. +/// All references within expressions must resolve to a +/// [Decl][google.api.expr.v1alpha1.Decl] provided at type-check for an +/// expression to be valid. A reference may either be a bare identifier `name` or +/// a qualified identifier `google.api.name`. References may either refer to a +/// value or a function declaration. /// /// For example, the expression `google.api.name.startsWith('expr')` references -/// the declaration `google.api.name` within a [Expr.Select][google.api.expr.v1alpha1.Expr.Select] expression, and -/// the function declaration `startsWith`. +/// the declaration `google.api.name` within a +/// [Expr.Select][google.api.expr.v1alpha1.Expr.Select] expression, and the +/// function declaration `startsWith`. #[derive(Clone, PartialEq, ::prost::Message)] pub struct Expr { /// Required. An id assigned to this node by the parser which is unique in a @@ -53,7 +55,8 @@ pub mod expr { /// Required. Holds a single, unqualified identifier, possibly preceded by a /// '.'. /// - /// Qualified names are represented by the [Expr.Select][google.api.expr.v1alpha1.Expr.Select] expression. + /// Qualified names are represented by the + /// [Expr.Select][google.api.expr.v1alpha1.Expr.Select] expression. #[prost(string, tag = "1")] pub name: ::prost::alloc::string::String, } @@ -251,12 +254,50 @@ pub mod expr { /// messages `has(m.x)` is defined as 'defined, but not set`. For proto3, the /// macro tests whether the property is set to its default. For map and struct /// types, the macro tests whether the property `x` is defined on `m`. + /// + /// Comprehensions for the standard environment macros evaluation can be best + /// visualized as the following pseudocode: + /// + /// ``` + /// let `accu_var` = `accu_init` + /// for (let `iter_var` in `iter_range`) { + /// if (!`loop_condition`) { + /// break + /// } + /// `accu_var` = `loop_step` + /// } + /// return `result` + /// ``` + /// + /// Comprehensions for the optional V2 macros which support map-to-map + /// translation differ slightly from the standard environment macros in that + /// they expose both the key or index in addition to the value for each list + /// or map entry: + /// + /// ``` + /// let `accu_var` = `accu_init` + /// for (let `iter_var`, `iter_var2` in `iter_range`) { + /// if (!`loop_condition`) { + /// break + /// } + /// `accu_var` = `loop_step` + /// } + /// return `result` + /// ``` #[derive(Clone, PartialEq, ::prost::Message)] pub struct Comprehension { - /// The name of the iteration variable. + /// The name of the first iteration variable. + /// When the iter_range is a list, this variable is the list element. + /// When the iter_range is a map, this variable is the map entry key. #[prost(string, tag = "1")] pub iter_var: ::prost::alloc::string::String, - /// The range over which var iterates. + /// The name of the second iteration variable, empty if not set. + /// When the iter_range is a list, this variable is the integer index. + /// When the iter_range is a map, this variable is the map entry value. + /// This field is only set for comprehension v2 macros. + #[prost(string, tag = "8")] + pub iter_var2: ::prost::alloc::string::String, + /// The range over which the comprehension iterates. #[prost(message, optional, boxed, tag = "2")] pub iter_range: ::core::option::Option<::prost::alloc::boxed::Box>, /// The name of the variable used for accumulation of the result. @@ -265,7 +306,7 @@ pub mod expr { /// The initial value of the accumulator. #[prost(message, optional, boxed, tag = "4")] pub accu_init: ::core::option::Option<::prost::alloc::boxed::Box>, - /// An expression which can contain iter_var and accu_var. + /// An expression which can contain iter_var, iter_var2, and accu_var. /// /// Returns false when the result has been computed and may be used as /// a hint to short-circuit the remainder of the comprehension. @@ -273,7 +314,7 @@ pub mod expr { pub loop_condition: ::core::option::Option< ::prost::alloc::boxed::Box, >, - /// An expression which can contain iter_var and accu_var. + /// An expression which can contain iter_var, iter_var2, and accu_var. /// /// Computes the next value of accu_var. #[prost(message, optional, boxed, tag = "6")] @@ -339,7 +380,8 @@ impl ::prost::Name for Expr { /// primitives. /// /// Lists and structs are not included as constants as these aggregate types may -/// contain [Expr][google.api.expr.v1alpha1.Expr] elements which require evaluation and are thus not constant. +/// contain [Expr][google.api.expr.v1alpha1.Expr] elements which require +/// evaluation and are thus not constant. /// /// Examples of literals include: `"hello"`, `b'bytes'`, `1u`, `4.2`, `-2`, /// `true`, `null`. @@ -435,6 +477,119 @@ pub struct SourceInfo { /// value is the call `Expr` that was replaced. #[prost(map = "int64, message", tag = "5")] pub macro_calls: ::std::collections::HashMap, + /// A list of tags for extensions that were used while parsing or type checking + /// the source expression. For example, optimizations that require special + /// runtime support may be specified. + /// + /// These are used to check feature support between components in separate + /// implementations. This can be used to either skip redundant work or + /// report an error if the extension is unsupported. + #[prost(message, repeated, tag = "6")] + pub extensions: ::prost::alloc::vec::Vec, +} +/// Nested message and enum types in `SourceInfo`. +pub mod source_info { + /// An extension that was requested for the source expression. + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct Extension { + /// Identifier for the extension. Example: constant_folding + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + /// If set, the listed components must understand the extension for the + /// expression to evaluate correctly. + /// + /// This field has set semantics, repeated values should be deduplicated. + #[prost(enumeration = "extension::Component", repeated, tag = "2")] + pub affected_components: ::prost::alloc::vec::Vec, + /// Version info. May be skipped if it isn't meaningful for the extension. + /// (for example constant_folding might always be v0.0). + #[prost(message, optional, tag = "3")] + pub version: ::core::option::Option, + } + /// Nested message and enum types in `Extension`. + pub mod extension { + /// Version + #[derive(Clone, Copy, PartialEq, ::prost::Message)] + pub struct Version { + /// Major version changes indicate different required support level from + /// the required components. + #[prost(int64, tag = "1")] + pub major: i64, + /// Minor version changes must not change the observed behavior from + /// existing implementations, but may be provided informationally. + #[prost(int64, tag = "2")] + pub minor: i64, + } + impl ::prost::Name for Version { + const NAME: &'static str = "Version"; + const PACKAGE: &'static str = "google.api.expr.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + "google.api.expr.v1alpha1.SourceInfo.Extension.Version".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/google.api.expr.v1alpha1.SourceInfo.Extension.Version".into() + } + } + /// CEL component specifier. + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum Component { + /// Unspecified, default. + Unspecified = 0, + /// Parser. Converts a CEL string to an AST. + Parser = 1, + /// Type checker. Checks that references in an AST are defined and types + /// agree. + TypeChecker = 2, + /// Runtime. Evaluates a parsed and optionally checked CEL AST against a + /// context. + Runtime = 3, + } + impl Component { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "COMPONENT_UNSPECIFIED", + Self::Parser => "COMPONENT_PARSER", + Self::TypeChecker => "COMPONENT_TYPE_CHECKER", + Self::Runtime => "COMPONENT_RUNTIME", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "COMPONENT_UNSPECIFIED" => Some(Self::Unspecified), + "COMPONENT_PARSER" => Some(Self::Parser), + "COMPONENT_TYPE_CHECKER" => Some(Self::TypeChecker), + "COMPONENT_RUNTIME" => Some(Self::Runtime), + _ => None, + } + } + } + } + impl ::prost::Name for Extension { + const NAME: &'static str = "Extension"; + const PACKAGE: &'static str = "google.api.expr.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + "google.api.expr.v1alpha1.SourceInfo.Extension".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/google.api.expr.v1alpha1.SourceInfo.Extension".into() + } + } } impl ::prost::Name for SourceInfo { const NAME: &'static str = "SourceInfo"; diff --git a/src/generated/google.api.expr.v1alpha1.serde.rs b/src/generated/google.api.expr.v1alpha1.serde.rs index b02b375..d1c1f51 100644 --- a/src/generated/google.api.expr.v1alpha1.serde.rs +++ b/src/generated/google.api.expr.v1alpha1.serde.rs @@ -1237,6 +1237,9 @@ impl serde::Serialize for expr::Comprehension { if !self.iter_var.is_empty() { len += 1; } + if !self.iter_var2.is_empty() { + len += 1; + } if self.iter_range.is_some() { len += 1; } @@ -1259,6 +1262,9 @@ impl serde::Serialize for expr::Comprehension { if !self.iter_var.is_empty() { struct_ser.serialize_field("iter_var", &self.iter_var)?; } + if !self.iter_var2.is_empty() { + struct_ser.serialize_field("iter_var2", &self.iter_var2)?; + } if let Some(v) = self.iter_range.as_ref() { struct_ser.serialize_field("iter_range", v)?; } @@ -1289,6 +1295,8 @@ impl<'de> serde::Deserialize<'de> for expr::Comprehension { const FIELDS: &[&str] = &[ "iter_var", "iterVar", + "iter_var2", + "iterVar2", "iter_range", "iterRange", "accu_var", @@ -1305,6 +1313,7 @@ impl<'de> serde::Deserialize<'de> for expr::Comprehension { #[allow(clippy::enum_variant_names)] enum GeneratedField { IterVar, + IterVar2, IterRange, AccuVar, AccuInit, @@ -1333,6 +1342,7 @@ impl<'de> serde::Deserialize<'de> for expr::Comprehension { { match value { "iterVar" | "iter_var" => Ok(GeneratedField::IterVar), + "iterVar2" | "iter_var2" => Ok(GeneratedField::IterVar2), "iterRange" | "iter_range" => Ok(GeneratedField::IterRange), "accuVar" | "accu_var" => Ok(GeneratedField::AccuVar), "accuInit" | "accu_init" => Ok(GeneratedField::AccuInit), @@ -1359,6 +1369,7 @@ impl<'de> serde::Deserialize<'de> for expr::Comprehension { V: serde::de::MapAccess<'de>, { let mut iter_var__ = None; + let mut iter_var2__ = None; let mut iter_range__ = None; let mut accu_var__ = None; let mut accu_init__ = None; @@ -1373,6 +1384,12 @@ impl<'de> serde::Deserialize<'de> for expr::Comprehension { } iter_var__ = Some(map_.next_value()?); } + GeneratedField::IterVar2 => { + if iter_var2__.is_some() { + return Err(serde::de::Error::duplicate_field("iterVar2")); + } + iter_var2__ = Some(map_.next_value()?); + } GeneratedField::IterRange => { if iter_range__.is_some() { return Err(serde::de::Error::duplicate_field("iterRange")); @@ -1413,6 +1430,7 @@ impl<'de> serde::Deserialize<'de> for expr::Comprehension { } Ok(expr::Comprehension { iter_var: iter_var__.unwrap_or_default(), + iter_var2: iter_var2__.unwrap_or_default(), iter_range: iter_range__, accu_var: accu_var__.unwrap_or_default(), accu_init: accu_init__, @@ -2287,6 +2305,9 @@ impl serde::Serialize for SourceInfo { if !self.macro_calls.is_empty() { len += 1; } + if !self.extensions.is_empty() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("google.api.expr.v1alpha1.SourceInfo", len)?; if !self.syntax_version.is_empty() { struct_ser.serialize_field("syntax_version", &self.syntax_version)?; @@ -2303,6 +2324,9 @@ impl serde::Serialize for SourceInfo { if !self.macro_calls.is_empty() { struct_ser.serialize_field("macro_calls", &self.macro_calls)?; } + if !self.extensions.is_empty() { + struct_ser.serialize_field("extensions", &self.extensions)?; + } struct_ser.end() } } @@ -2321,6 +2345,7 @@ impl<'de> serde::Deserialize<'de> for SourceInfo { "positions", "macro_calls", "macroCalls", + "extensions", ]; #[allow(clippy::enum_variant_names)] @@ -2330,6 +2355,7 @@ impl<'de> serde::Deserialize<'de> for SourceInfo { LineOffsets, Positions, MacroCalls, + Extensions, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -2356,6 +2382,7 @@ impl<'de> serde::Deserialize<'de> for SourceInfo { "lineOffsets" | "line_offsets" => Ok(GeneratedField::LineOffsets), "positions" => Ok(GeneratedField::Positions), "macroCalls" | "macro_calls" => Ok(GeneratedField::MacroCalls), + "extensions" => Ok(GeneratedField::Extensions), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -2380,6 +2407,7 @@ impl<'de> serde::Deserialize<'de> for SourceInfo { let mut line_offsets__ = None; let mut positions__ = None; let mut macro_calls__ = None; + let mut extensions__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::SyntaxVersion => { @@ -2421,6 +2449,12 @@ impl<'de> serde::Deserialize<'de> for SourceInfo { .into_iter().map(|(k,v)| (k.0, v)).collect() ); } + GeneratedField::Extensions => { + if extensions__.is_some() { + return Err(serde::de::Error::duplicate_field("extensions")); + } + extensions__ = Some(map_.next_value()?); + } } } Ok(SourceInfo { @@ -2429,12 +2463,336 @@ impl<'de> serde::Deserialize<'de> for SourceInfo { line_offsets: line_offsets__.unwrap_or_default(), positions: positions__.unwrap_or_default(), macro_calls: macro_calls__.unwrap_or_default(), + extensions: extensions__.unwrap_or_default(), }) } } deserializer.deserialize_struct("google.api.expr.v1alpha1.SourceInfo", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for source_info::Extension { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.id.is_empty() { + len += 1; + } + if !self.affected_components.is_empty() { + len += 1; + } + if self.version.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("google.api.expr.v1alpha1.SourceInfo.Extension", len)?; + if !self.id.is_empty() { + struct_ser.serialize_field("id", &self.id)?; + } + if !self.affected_components.is_empty() { + let v = self.affected_components.iter().cloned().map(|v| { + source_info::extension::Component::try_from(v) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", v))) + }).collect::, _>>()?; + struct_ser.serialize_field("affected_components", &v)?; + } + if let Some(v) = self.version.as_ref() { + struct_ser.serialize_field("version", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for source_info::Extension { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "id", + "affected_components", + "affectedComponents", + "version", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Id, + AffectedComponents, + Version, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "id" => Ok(GeneratedField::Id), + "affectedComponents" | "affected_components" => Ok(GeneratedField::AffectedComponents), + "version" => Ok(GeneratedField::Version), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = source_info::Extension; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct google.api.expr.v1alpha1.SourceInfo.Extension") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut id__ = None; + let mut affected_components__ = None; + let mut version__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Id => { + if id__.is_some() { + return Err(serde::de::Error::duplicate_field("id")); + } + id__ = Some(map_.next_value()?); + } + GeneratedField::AffectedComponents => { + if affected_components__.is_some() { + return Err(serde::de::Error::duplicate_field("affectedComponents")); + } + affected_components__ = Some(map_.next_value::>()?.into_iter().map(|x| x as i32).collect()); + } + GeneratedField::Version => { + if version__.is_some() { + return Err(serde::de::Error::duplicate_field("version")); + } + version__ = map_.next_value()?; + } + } + } + Ok(source_info::Extension { + id: id__.unwrap_or_default(), + affected_components: affected_components__.unwrap_or_default(), + version: version__, + }) + } + } + deserializer.deserialize_struct("google.api.expr.v1alpha1.SourceInfo.Extension", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for source_info::extension::Component { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + let variant = match self { + Self::Unspecified => "COMPONENT_UNSPECIFIED", + Self::Parser => "COMPONENT_PARSER", + Self::TypeChecker => "COMPONENT_TYPE_CHECKER", + Self::Runtime => "COMPONENT_RUNTIME", + }; + serializer.serialize_str(variant) + } +} +impl<'de> serde::Deserialize<'de> for source_info::extension::Component { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "COMPONENT_UNSPECIFIED", + "COMPONENT_PARSER", + "COMPONENT_TYPE_CHECKER", + "COMPONENT_RUNTIME", + ]; + + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = source_info::extension::Component; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + fn visit_i64(self, v: i64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) + }) + } + + fn visit_u64(self, v: u64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) + }) + } + + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "COMPONENT_UNSPECIFIED" => Ok(source_info::extension::Component::Unspecified), + "COMPONENT_PARSER" => Ok(source_info::extension::Component::Parser), + "COMPONENT_TYPE_CHECKER" => Ok(source_info::extension::Component::TypeChecker), + "COMPONENT_RUNTIME" => Ok(source_info::extension::Component::Runtime), + _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), + } + } + } + deserializer.deserialize_any(GeneratedVisitor) + } +} +impl serde::Serialize for source_info::extension::Version { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.major != 0 { + len += 1; + } + if self.minor != 0 { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("google.api.expr.v1alpha1.SourceInfo.Extension.Version", len)?; + if self.major != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("major", ToString::to_string(&self.major).as_str())?; + } + if self.minor != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("minor", ToString::to_string(&self.minor).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for source_info::extension::Version { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "major", + "minor", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Major, + Minor, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "major" => Ok(GeneratedField::Major), + "minor" => Ok(GeneratedField::Minor), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = source_info::extension::Version; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct google.api.expr.v1alpha1.SourceInfo.Extension.Version") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut major__ = None; + let mut minor__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Major => { + if major__.is_some() { + return Err(serde::de::Error::duplicate_field("major")); + } + major__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::Minor => { + if minor__.is_some() { + return Err(serde::de::Error::duplicate_field("minor")); + } + minor__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + } + } + Ok(source_info::extension::Version { + major: major__.unwrap_or_default(), + minor: minor__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("google.api.expr.v1alpha1.SourceInfo.Extension.Version", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for SourcePosition { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/src/generated/google.api.rs b/src/generated/google.api.rs index 7debc7f..7580938 100644 --- a/src/generated/google.api.rs +++ b/src/generated/google.api.rs @@ -28,7 +28,7 @@ impl ::prost::Name for Http { "/google.api.Http".into() } } -/// # gRPC Transcoding +/// gRPC Transcoding /// /// gRPC Transcoding is a feature for mapping between a gRPC method and one or /// more HTTP REST endpoints. It allows developers to build a single API service @@ -69,9 +69,8 @@ impl ::prost::Name for Http { /// /// This enables an HTTP REST to gRPC mapping as below: /// -/// HTTP | gRPC -/// -----|----- -/// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")` +/// - HTTP: `GET /v1/messages/123456` +/// - gRPC: `GetMessage(name: "messages/123456")` /// /// Any fields in the request message which are not bound by the path template /// automatically become HTTP query parameters if there is no HTTP request body. @@ -95,11 +94,9 @@ impl ::prost::Name for Http { /// /// This enables a HTTP JSON to RPC mapping as below: /// -/// HTTP | gRPC -/// -----|----- -/// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | -/// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: -/// "foo"))` +/// - HTTP: `GET /v1/messages/123456?revision=2&sub.subfield=foo` +/// - gRPC: `GetMessage(message_id: "123456" revision: 2 sub: +/// SubMessage(subfield: "foo"))` /// /// Note that fields which are mapped to URL query parameters must have a /// primitive type or a repeated primitive type or a non-repeated message type. @@ -129,10 +126,8 @@ impl ::prost::Name for Http { /// representation of the JSON in the request body is determined by /// protos JSON encoding: /// -/// HTTP | gRPC -/// -----|----- -/// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: -/// "123456" message { text: "Hi!" })` +/// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }` +/// - gRPC: `UpdateMessage(message_id: "123456" message { text: "Hi!" })` /// /// The special name `*` can be used in the body mapping to define that /// every field not bound by the path template should be mapped to the @@ -155,10 +150,8 @@ impl ::prost::Name for Http { /// /// The following HTTP JSON to RPC mapping is enabled: /// -/// HTTP | gRPC -/// -----|----- -/// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: -/// "123456" text: "Hi!")` +/// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }` +/// - gRPC: `UpdateMessage(message_id: "123456" text: "Hi!")` /// /// Note that when using `*` in the body mapping, it is not possible to /// have HTTP parameters, as all fields not bound by the path end in @@ -186,29 +179,32 @@ impl ::prost::Name for Http { /// /// This enables the following two alternative HTTP JSON to RPC mappings: /// -/// HTTP | gRPC -/// -----|----- -/// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` -/// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: -/// "123456")` +/// - HTTP: `GET /v1/messages/123456` +/// - gRPC: `GetMessage(message_id: "123456")` /// -/// ## Rules for HTTP mapping +/// - HTTP: `GET /v1/users/me/messages/123456` +/// - gRPC: `GetMessage(user_id: "me" message_id: "123456")` +/// +/// Rules for HTTP mapping /// /// 1. Leaf request fields (recursive expansion nested messages in the request /// message) are classified into three categories: /// - Fields referred by the path template. They are passed via the URL path. -/// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They are passed via the HTTP +/// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They +/// are passed via the HTTP /// request body. /// - All other fields are passed via the URL query parameters, and the /// parameter name is the field path in the request message. A repeated /// field can be represented as multiple query parameters under the same /// name. -/// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL query parameter, all fields +/// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL +/// query parameter, all fields /// are passed via URL path and HTTP request body. -/// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP request body, all +/// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP +/// request body, all /// fields are passed via URL path and URL query parameters. /// -/// ### Path template syntax +/// Path template syntax /// /// Template = "/" Segments \[ Verb \] ; /// Segments = Segment { "/" Segment } ; @@ -247,7 +243,7 @@ impl ::prost::Name for Http { /// Document]() as /// `{+var}`. /// -/// ## Using gRPC API Service Configuration +/// Using gRPC API Service Configuration /// /// gRPC API Service Configuration (service config) is a configuration language /// for configuring a gRPC service to become a user-facing product. The @@ -262,15 +258,14 @@ impl ::prost::Name for Http { /// specified in the service config will override any matching transcoding /// configuration in the proto. /// -/// Example: +/// The following example selects a gRPC method and applies an `HttpRule` to it: /// /// http: /// rules: -/// # Selects a gRPC method and applies HttpRule to it. /// - selector: example.v1.Messaging.GetMessage /// get: /v1/messages/{message_id}/{sub.subfield} /// -/// ## Special notes +/// Special notes /// /// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the /// proto to JSON conversion must follow the [proto3 @@ -301,7 +296,8 @@ impl ::prost::Name for Http { pub struct HttpRule { /// Selects a method to which this rule applies. /// - /// Refer to [selector][google.api.DocumentationRule.selector] for syntax details. + /// Refer to [selector][google.api.DocumentationRule.selector] for syntax + /// details. #[prost(string, tag = "1")] pub selector: ::prost::alloc::string::String, /// The name of the request field whose value is mapped to the HTTP request diff --git a/src/generated/google.protobuf.rs b/src/generated/google.protobuf.rs index 561d297..71ad2f9 100644 --- a/src/generated/google.protobuf.rs +++ b/src/generated/google.protobuf.rs @@ -120,6 +120,10 @@ pub struct FileDescriptorProto { /// For Google-internal migration only. Do not use. #[prost(int32, repeated, packed = "false", tag = "11")] pub weak_dependency: ::prost::alloc::vec::Vec, + /// Names of files imported by this file purely for the purpose of providing + /// option extensions. These are excluded from the dependency list above. + #[prost(string, repeated, tag = "15")] + pub option_dependency: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, /// All top-level definitions in this file. #[prost(message, repeated, tag = "4")] pub message_type: ::prost::alloc::vec::Vec, @@ -141,9 +145,15 @@ pub struct FileDescriptorProto { /// The supported values are "proto2", "proto3", and "editions". /// /// If `edition` is present, this value must be "editions". + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. #[prost(string, optional, tag = "12")] pub syntax: ::core::option::Option<::prost::alloc::string::String>, /// The edition of the proto file. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. #[prost(enumeration = "Edition", optional, tag = "14")] pub edition: ::core::option::Option, } @@ -182,6 +192,9 @@ pub struct DescriptorProto { /// A given name may only be reserved once. #[prost(string, repeated, tag = "10")] pub reserved_name: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// Support for `export` and `local` keywords on enums. + #[prost(enumeration = "SymbolVisibility", optional, tag = "11")] + pub visibility: ::core::option::Option, } /// Nested message and enum types in `DescriptorProto`. pub mod descriptor_proto { @@ -607,6 +620,9 @@ pub struct EnumDescriptorProto { /// be reserved once. #[prost(string, repeated, tag = "5")] pub reserved_name: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// Support for `export` and `local` keywords on enums. + #[prost(enumeration = "SymbolVisibility", optional, tag = "6")] + pub visibility: ::core::option::Option, } /// Nested message and enum types in `EnumDescriptorProto`. pub mod enum_descriptor_proto { @@ -828,6 +844,9 @@ pub struct FileOptions { #[prost(string, optional, tag = "45")] pub ruby_package: ::core::option::Option<::prost::alloc::string::String>, /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. #[prost(message, optional, tag = "50")] pub features: ::core::option::Option, /// The parser stores options it doesn't recognize here. @@ -963,6 +982,9 @@ pub struct MessageOptions { #[prost(bool, optional, tag = "11")] pub deprecated_legacy_json_field_conflicts: ::core::option::Option, /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. #[prost(message, optional, tag = "12")] pub features: ::core::option::Option, /// The parser stores options it doesn't recognize here. See above. @@ -981,12 +1003,13 @@ impl ::prost::Name for MessageOptions { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct FieldOptions { + /// NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead. /// The ctype option instructs the C++ code generator to use a different /// representation of the field than it normally would. See the specific /// options below. This option is only implemented to support use of /// \[ctype=CORD\] and \[ctype=STRING\] (the default) on non-repeated fields of - /// type "bytes" in the open source release -- sorry, we'll try to include - /// other types in a future version! + /// type "bytes" in the open source release. + /// TODO: make ctype actually deprecated. #[prost( enumeration = "field_options::CType", optional, @@ -1075,6 +1098,9 @@ pub struct FieldOptions { #[prost(message, repeated, tag = "20")] pub edition_defaults: ::prost::alloc::vec::Vec, /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. #[prost(message, optional, tag = "21")] pub features: ::core::option::Option, #[prost(message, optional, tag = "22")] @@ -1224,8 +1250,6 @@ pub mod field_options { } } /// If set to RETENTION_SOURCE, the option will be omitted from the binary. - /// Note: as of January 2023, support for this is in progress and does not yet - /// have an effect (b/264593489). #[derive( Clone, Copy, @@ -1267,8 +1291,7 @@ pub mod field_options { } /// This indicates the types of entities that the field may apply to when used /// as an option. If it is unset, then the field may be freely used as an - /// option on any kind of entity. Note: as of January 2023, support for this is - /// in progress and does not yet have an effect (b/264593489). + /// option on any kind of entity. #[derive( Clone, Copy, @@ -1343,6 +1366,9 @@ impl ::prost::Name for FieldOptions { #[derive(Clone, PartialEq, ::prost::Message)] pub struct OneofOptions { /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. #[prost(message, optional, tag = "1")] pub features: ::core::option::Option, /// The parser stores options it doesn't recognize here. See above. @@ -1381,6 +1407,9 @@ pub struct EnumOptions { #[prost(bool, optional, tag = "6")] pub deprecated_legacy_json_field_conflicts: ::core::option::Option, /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. #[prost(message, optional, tag = "7")] pub features: ::core::option::Option, /// The parser stores options it doesn't recognize here. See above. @@ -1406,6 +1435,9 @@ pub struct EnumValueOptions { #[prost(bool, optional, tag = "1", default = "false")] pub deprecated: ::core::option::Option, /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. #[prost(message, optional, tag = "2")] pub features: ::core::option::Option, /// Indicate that fields annotated with this enum value should not be printed @@ -1433,6 +1465,9 @@ impl ::prost::Name for EnumValueOptions { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ServiceOptions { /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. #[prost(message, optional, tag = "34")] pub features: ::core::option::Option, /// Is this service deprecated? @@ -1471,6 +1506,9 @@ pub struct MethodOptions { )] pub idempotency_level: ::core::option::Option, /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. #[prost(message, optional, tag = "35")] pub features: ::core::option::Option, /// The parser stores options it doesn't recognize here. See above. @@ -1614,9 +1652,83 @@ pub struct FeatureSet { pub message_encoding: ::core::option::Option, #[prost(enumeration = "feature_set::JsonFormat", optional, tag = "6")] pub json_format: ::core::option::Option, + #[prost(enumeration = "feature_set::EnforceNamingStyle", optional, tag = "7")] + pub enforce_naming_style: ::core::option::Option, + #[prost( + enumeration = "feature_set::visibility_feature::DefaultSymbolVisibility", + optional, + tag = "8" + )] + pub default_symbol_visibility: ::core::option::Option, } /// Nested message and enum types in `FeatureSet`. pub mod feature_set { + #[derive(Clone, Copy, PartialEq, ::prost::Message)] + pub struct VisibilityFeature {} + /// Nested message and enum types in `VisibilityFeature`. + pub mod visibility_feature { + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum DefaultSymbolVisibility { + Unknown = 0, + /// Default pre-EDITION_2024, all UNSET visibility are export. + ExportAll = 1, + /// All top-level symbols default to export, nested default to local. + ExportTopLevel = 2, + /// All symbols default to local. + LocalAll = 3, + /// All symbols local by default. Nested types cannot be exported. + /// With special case caveat for message { enum {} reserved 1 to max; } + /// This is the recommended setting for new protos. + Strict = 4, + } + impl DefaultSymbolVisibility { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unknown => "DEFAULT_SYMBOL_VISIBILITY_UNKNOWN", + Self::ExportAll => "EXPORT_ALL", + Self::ExportTopLevel => "EXPORT_TOP_LEVEL", + Self::LocalAll => "LOCAL_ALL", + Self::Strict => "STRICT", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "DEFAULT_SYMBOL_VISIBILITY_UNKNOWN" => Some(Self::Unknown), + "EXPORT_ALL" => Some(Self::ExportAll), + "EXPORT_TOP_LEVEL" => Some(Self::ExportTopLevel), + "LOCAL_ALL" => Some(Self::LocalAll), + "STRICT" => Some(Self::Strict), + _ => None, + } + } + } + } + impl ::prost::Name for VisibilityFeature { + const NAME: &'static str = "VisibilityFeature"; + const PACKAGE: &'static str = "google.protobuf"; + fn full_name() -> ::prost::alloc::string::String { + "google.protobuf.FeatureSet.VisibilityFeature".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/google.protobuf.FeatureSet.VisibilityFeature".into() + } + } #[derive( Clone, Copy, @@ -1854,6 +1966,45 @@ pub mod feature_set { } } } + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum EnforceNamingStyle { + Unknown = 0, + Style2024 = 1, + StyleLegacy = 2, + } + impl EnforceNamingStyle { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unknown => "ENFORCE_NAMING_STYLE_UNKNOWN", + Self::Style2024 => "STYLE2024", + Self::StyleLegacy => "STYLE_LEGACY", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "ENFORCE_NAMING_STYLE_UNKNOWN" => Some(Self::Unknown), + "STYLE2024" => Some(Self::Style2024), + "STYLE_LEGACY" => Some(Self::StyleLegacy), + _ => None, + } + } + } } impl ::prost::Name for FeatureSet { const NAME: &'static str = "FeatureSet"; @@ -2207,7 +2358,7 @@ pub enum Edition { Edition2023 = 1000, Edition2024 = 1001, /// Placeholder editions for testing feature resolution. These should not be - /// used or relyed on outside of tests. + /// used or relied on outside of tests. Edition1TestOnly = 1, Edition2TestOnly = 2, Edition99997TestOnly = 99997, @@ -2258,6 +2409,40 @@ impl Edition { } } } +/// Describes the 'visibility' of a symbol with respect to the proto import +/// system. Symbols can only be imported when the visibility rules do not prevent +/// it (ex: local symbols cannot be imported). Visibility modifiers can only set +/// on `message` and `enum` as they are the only types available to be referenced +/// from other files. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum SymbolVisibility { + VisibilityUnset = 0, + VisibilityLocal = 1, + VisibilityExport = 2, +} +impl SymbolVisibility { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::VisibilityUnset => "VISIBILITY_UNSET", + Self::VisibilityLocal => "VISIBILITY_LOCAL", + Self::VisibilityExport => "VISIBILITY_EXPORT", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "VISIBILITY_UNSET" => Some(Self::VisibilityUnset), + "VISIBILITY_LOCAL" => Some(Self::VisibilityLocal), + "VISIBILITY_EXPORT" => Some(Self::VisibilityExport), + _ => None, + } + } +} /// A Timestamp represents a point in time independent of any time zone or local /// calendar, encoded as a count of seconds and fractions of seconds at /// nanosecond resolution. The count is relative to an epoch at UTC midnight on @@ -2375,6 +2560,9 @@ impl ::prost::Name for Timestamp { /// Wrapper message for `double`. /// /// The JSON representation for `DoubleValue` is JSON number. +/// +/// Not recommended for use in new APIs, but still useful for legacy APIs and +/// has no plan to be removed. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct DoubleValue { /// The double value. @@ -2394,6 +2582,9 @@ impl ::prost::Name for DoubleValue { /// Wrapper message for `float`. /// /// The JSON representation for `FloatValue` is JSON number. +/// +/// Not recommended for use in new APIs, but still useful for legacy APIs and +/// has no plan to be removed. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct FloatValue { /// The float value. @@ -2413,6 +2604,9 @@ impl ::prost::Name for FloatValue { /// Wrapper message for `int64`. /// /// The JSON representation for `Int64Value` is JSON string. +/// +/// Not recommended for use in new APIs, but still useful for legacy APIs and +/// has no plan to be removed. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct Int64Value { /// The int64 value. @@ -2432,6 +2626,9 @@ impl ::prost::Name for Int64Value { /// Wrapper message for `uint64`. /// /// The JSON representation for `UInt64Value` is JSON string. +/// +/// Not recommended for use in new APIs, but still useful for legacy APIs and +/// has no plan to be removed. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct UInt64Value { /// The uint64 value. @@ -2451,6 +2648,9 @@ impl ::prost::Name for UInt64Value { /// Wrapper message for `int32`. /// /// The JSON representation for `Int32Value` is JSON number. +/// +/// Not recommended for use in new APIs, but still useful for legacy APIs and +/// has no plan to be removed. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct Int32Value { /// The int32 value. @@ -2470,6 +2670,9 @@ impl ::prost::Name for Int32Value { /// Wrapper message for `uint32`. /// /// The JSON representation for `UInt32Value` is JSON number. +/// +/// Not recommended for use in new APIs, but still useful for legacy APIs and +/// has no plan to be removed. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct UInt32Value { /// The uint32 value. @@ -2489,6 +2692,9 @@ impl ::prost::Name for UInt32Value { /// Wrapper message for `bool`. /// /// The JSON representation for `BoolValue` is JSON `true` and `false`. +/// +/// Not recommended for use in new APIs, but still useful for legacy APIs and +/// has no plan to be removed. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct BoolValue { /// The bool value. @@ -2508,6 +2714,9 @@ impl ::prost::Name for BoolValue { /// Wrapper message for `string`. /// /// The JSON representation for `StringValue` is JSON string. +/// +/// Not recommended for use in new APIs, but still useful for legacy APIs and +/// has no plan to be removed. #[derive(Clone, PartialEq, ::prost::Message)] pub struct StringValue { /// The string value. @@ -2527,6 +2736,9 @@ impl ::prost::Name for StringValue { /// Wrapper message for `bytes`. /// /// The JSON representation for `BytesValue` is JSON string. +/// +/// Not recommended for use in new APIs, but still useful for legacy APIs and +/// has no plan to be removed. #[derive(Clone, PartialEq, ::prost::Message)] pub struct BytesValue { /// The bytes value. diff --git a/src/generated/google.protobuf.serde.rs b/src/generated/google.protobuf.serde.rs index 7c237a6..75ec22d 100644 --- a/src/generated/google.protobuf.serde.rs +++ b/src/generated/google.protobuf.serde.rs @@ -222,6 +222,9 @@ impl serde::Serialize for DescriptorProto { if !self.reserved_name.is_empty() { len += 1; } + if self.visibility.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("google.protobuf.DescriptorProto", len)?; if let Some(v) = self.name.as_ref() { struct_ser.serialize_field("name", v)?; @@ -253,6 +256,11 @@ impl serde::Serialize for DescriptorProto { if !self.reserved_name.is_empty() { struct_ser.serialize_field("reserved_name", &self.reserved_name)?; } + if let Some(v) = self.visibility.as_ref() { + let v = SymbolVisibility::try_from(*v) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", *v)))?; + struct_ser.serialize_field("visibility", &v)?; + } struct_ser.end() } } @@ -279,6 +287,7 @@ impl<'de> serde::Deserialize<'de> for DescriptorProto { "reservedRange", "reserved_name", "reservedName", + "visibility", ]; #[allow(clippy::enum_variant_names)] @@ -293,6 +302,7 @@ impl<'de> serde::Deserialize<'de> for DescriptorProto { Options, ReservedRange, ReservedName, + Visibility, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -324,6 +334,7 @@ impl<'de> serde::Deserialize<'de> for DescriptorProto { "options" => Ok(GeneratedField::Options), "reservedRange" | "reserved_range" => Ok(GeneratedField::ReservedRange), "reservedName" | "reserved_name" => Ok(GeneratedField::ReservedName), + "visibility" => Ok(GeneratedField::Visibility), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -353,6 +364,7 @@ impl<'de> serde::Deserialize<'de> for DescriptorProto { let mut options__ = None; let mut reserved_range__ = None; let mut reserved_name__ = None; + let mut visibility__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Name => { @@ -415,6 +427,12 @@ impl<'de> serde::Deserialize<'de> for DescriptorProto { } reserved_name__ = Some(map_.next_value()?); } + GeneratedField::Visibility => { + if visibility__.is_some() { + return Err(serde::de::Error::duplicate_field("visibility")); + } + visibility__ = map_.next_value::<::std::option::Option>()?.map(|x| x as i32); + } } } Ok(DescriptorProto { @@ -428,6 +446,7 @@ impl<'de> serde::Deserialize<'de> for DescriptorProto { options: options__, reserved_range: reserved_range__.unwrap_or_default(), reserved_name: reserved_name__.unwrap_or_default(), + visibility: visibility__, }) } } @@ -1077,6 +1096,9 @@ impl serde::Serialize for EnumDescriptorProto { if !self.reserved_name.is_empty() { len += 1; } + if self.visibility.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("google.protobuf.EnumDescriptorProto", len)?; if let Some(v) = self.name.as_ref() { struct_ser.serialize_field("name", v)?; @@ -1093,6 +1115,11 @@ impl serde::Serialize for EnumDescriptorProto { if !self.reserved_name.is_empty() { struct_ser.serialize_field("reserved_name", &self.reserved_name)?; } + if let Some(v) = self.visibility.as_ref() { + let v = SymbolVisibility::try_from(*v) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", *v)))?; + struct_ser.serialize_field("visibility", &v)?; + } struct_ser.end() } } @@ -1110,6 +1137,7 @@ impl<'de> serde::Deserialize<'de> for EnumDescriptorProto { "reservedRange", "reserved_name", "reservedName", + "visibility", ]; #[allow(clippy::enum_variant_names)] @@ -1119,6 +1147,7 @@ impl<'de> serde::Deserialize<'de> for EnumDescriptorProto { Options, ReservedRange, ReservedName, + Visibility, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -1145,6 +1174,7 @@ impl<'de> serde::Deserialize<'de> for EnumDescriptorProto { "options" => Ok(GeneratedField::Options), "reservedRange" | "reserved_range" => Ok(GeneratedField::ReservedRange), "reservedName" | "reserved_name" => Ok(GeneratedField::ReservedName), + "visibility" => Ok(GeneratedField::Visibility), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -1169,6 +1199,7 @@ impl<'de> serde::Deserialize<'de> for EnumDescriptorProto { let mut options__ = None; let mut reserved_range__ = None; let mut reserved_name__ = None; + let mut visibility__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Name => { @@ -1201,6 +1232,12 @@ impl<'de> serde::Deserialize<'de> for EnumDescriptorProto { } reserved_name__ = Some(map_.next_value()?); } + GeneratedField::Visibility => { + if visibility__.is_some() { + return Err(serde::de::Error::duplicate_field("visibility")); + } + visibility__ = map_.next_value::<::std::option::Option>()?.map(|x| x as i32); + } } } Ok(EnumDescriptorProto { @@ -1209,6 +1246,7 @@ impl<'de> serde::Deserialize<'de> for EnumDescriptorProto { options: options__, reserved_range: reserved_range__.unwrap_or_default(), reserved_name: reserved_name__.unwrap_or_default(), + visibility: visibility__, }) } } @@ -2182,6 +2220,12 @@ impl serde::Serialize for FeatureSet { if self.json_format.is_some() { len += 1; } + if self.enforce_naming_style.is_some() { + len += 1; + } + if self.default_symbol_visibility.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("google.protobuf.FeatureSet", len)?; if let Some(v) = self.field_presence.as_ref() { let v = feature_set::FieldPresence::try_from(*v) @@ -2213,6 +2257,16 @@ impl serde::Serialize for FeatureSet { .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", *v)))?; struct_ser.serialize_field("json_format", &v)?; } + if let Some(v) = self.enforce_naming_style.as_ref() { + let v = feature_set::EnforceNamingStyle::try_from(*v) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", *v)))?; + struct_ser.serialize_field("enforce_naming_style", &v)?; + } + if let Some(v) = self.default_symbol_visibility.as_ref() { + let v = feature_set::visibility_feature::DefaultSymbolVisibility::try_from(*v) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", *v)))?; + struct_ser.serialize_field("default_symbol_visibility", &v)?; + } struct_ser.end() } } @@ -2235,6 +2289,10 @@ impl<'de> serde::Deserialize<'de> for FeatureSet { "messageEncoding", "json_format", "jsonFormat", + "enforce_naming_style", + "enforceNamingStyle", + "default_symbol_visibility", + "defaultSymbolVisibility", ]; #[allow(clippy::enum_variant_names)] @@ -2245,6 +2303,8 @@ impl<'de> serde::Deserialize<'de> for FeatureSet { Utf8Validation, MessageEncoding, JsonFormat, + EnforceNamingStyle, + DefaultSymbolVisibility, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -2272,6 +2332,8 @@ impl<'de> serde::Deserialize<'de> for FeatureSet { "utf8Validation" | "utf8_validation" => Ok(GeneratedField::Utf8Validation), "messageEncoding" | "message_encoding" => Ok(GeneratedField::MessageEncoding), "jsonFormat" | "json_format" => Ok(GeneratedField::JsonFormat), + "enforceNamingStyle" | "enforce_naming_style" => Ok(GeneratedField::EnforceNamingStyle), + "defaultSymbolVisibility" | "default_symbol_visibility" => Ok(GeneratedField::DefaultSymbolVisibility), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -2297,6 +2359,8 @@ impl<'de> serde::Deserialize<'de> for FeatureSet { let mut utf8_validation__ = None; let mut message_encoding__ = None; let mut json_format__ = None; + let mut enforce_naming_style__ = None; + let mut default_symbol_visibility__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::FieldPresence => { @@ -2335,6 +2399,18 @@ impl<'de> serde::Deserialize<'de> for FeatureSet { } json_format__ = map_.next_value::<::std::option::Option>()?.map(|x| x as i32); } + GeneratedField::EnforceNamingStyle => { + if enforce_naming_style__.is_some() { + return Err(serde::de::Error::duplicate_field("enforceNamingStyle")); + } + enforce_naming_style__ = map_.next_value::<::std::option::Option>()?.map(|x| x as i32); + } + GeneratedField::DefaultSymbolVisibility => { + if default_symbol_visibility__.is_some() { + return Err(serde::de::Error::duplicate_field("defaultSymbolVisibility")); + } + default_symbol_visibility__ = map_.next_value::<::std::option::Option>()?.map(|x| x as i32); + } } } Ok(FeatureSet { @@ -2344,12 +2420,88 @@ impl<'de> serde::Deserialize<'de> for FeatureSet { utf8_validation: utf8_validation__, message_encoding: message_encoding__, json_format: json_format__, + enforce_naming_style: enforce_naming_style__, + default_symbol_visibility: default_symbol_visibility__, }) } } deserializer.deserialize_struct("google.protobuf.FeatureSet", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for feature_set::EnforceNamingStyle { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + let variant = match self { + Self::Unknown => "ENFORCE_NAMING_STYLE_UNKNOWN", + Self::Style2024 => "STYLE2024", + Self::StyleLegacy => "STYLE_LEGACY", + }; + serializer.serialize_str(variant) + } +} +impl<'de> serde::Deserialize<'de> for feature_set::EnforceNamingStyle { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "ENFORCE_NAMING_STYLE_UNKNOWN", + "STYLE2024", + "STYLE_LEGACY", + ]; + + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = feature_set::EnforceNamingStyle; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + fn visit_i64(self, v: i64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) + }) + } + + fn visit_u64(self, v: u64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) + }) + } + + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "ENFORCE_NAMING_STYLE_UNKNOWN" => Ok(feature_set::EnforceNamingStyle::Unknown), + "STYLE2024" => Ok(feature_set::EnforceNamingStyle::Style2024), + "STYLE_LEGACY" => Ok(feature_set::EnforceNamingStyle::StyleLegacy), + _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), + } + } + } + deserializer.deserialize_any(GeneratedVisitor) + } +} impl serde::Serialize for feature_set::EnumType { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -2797,6 +2949,157 @@ impl<'de> serde::Deserialize<'de> for feature_set::Utf8Validation { deserializer.deserialize_any(GeneratedVisitor) } } +impl serde::Serialize for feature_set::VisibilityFeature { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let len = 0; + let struct_ser = serializer.serialize_struct("google.protobuf.FeatureSet.VisibilityFeature", len)?; + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for feature_set::VisibilityFeature { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + Err(serde::de::Error::unknown_field(value, FIELDS)) + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = feature_set::VisibilityFeature; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct google.protobuf.FeatureSet.VisibilityFeature") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + while map_.next_key::()?.is_some() { + let _ = map_.next_value::()?; + } + Ok(feature_set::VisibilityFeature { + }) + } + } + deserializer.deserialize_struct("google.protobuf.FeatureSet.VisibilityFeature", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for feature_set::visibility_feature::DefaultSymbolVisibility { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + let variant = match self { + Self::Unknown => "DEFAULT_SYMBOL_VISIBILITY_UNKNOWN", + Self::ExportAll => "EXPORT_ALL", + Self::ExportTopLevel => "EXPORT_TOP_LEVEL", + Self::LocalAll => "LOCAL_ALL", + Self::Strict => "STRICT", + }; + serializer.serialize_str(variant) + } +} +impl<'de> serde::Deserialize<'de> for feature_set::visibility_feature::DefaultSymbolVisibility { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "DEFAULT_SYMBOL_VISIBILITY_UNKNOWN", + "EXPORT_ALL", + "EXPORT_TOP_LEVEL", + "LOCAL_ALL", + "STRICT", + ]; + + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = feature_set::visibility_feature::DefaultSymbolVisibility; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + fn visit_i64(self, v: i64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) + }) + } + + fn visit_u64(self, v: u64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) + }) + } + + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "DEFAULT_SYMBOL_VISIBILITY_UNKNOWN" => Ok(feature_set::visibility_feature::DefaultSymbolVisibility::Unknown), + "EXPORT_ALL" => Ok(feature_set::visibility_feature::DefaultSymbolVisibility::ExportAll), + "EXPORT_TOP_LEVEL" => Ok(feature_set::visibility_feature::DefaultSymbolVisibility::ExportTopLevel), + "LOCAL_ALL" => Ok(feature_set::visibility_feature::DefaultSymbolVisibility::LocalAll), + "STRICT" => Ok(feature_set::visibility_feature::DefaultSymbolVisibility::Strict), + _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), + } + } + } + deserializer.deserialize_any(GeneratedVisitor) + } +} impl serde::Serialize for FeatureSetDefaults { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -4453,6 +4756,9 @@ impl serde::Serialize for FileDescriptorProto { if !self.weak_dependency.is_empty() { len += 1; } + if !self.option_dependency.is_empty() { + len += 1; + } if !self.message_type.is_empty() { len += 1; } @@ -4493,6 +4799,9 @@ impl serde::Serialize for FileDescriptorProto { if !self.weak_dependency.is_empty() { struct_ser.serialize_field("weak_dependency", &self.weak_dependency)?; } + if !self.option_dependency.is_empty() { + struct_ser.serialize_field("option_dependency", &self.option_dependency)?; + } if !self.message_type.is_empty() { struct_ser.serialize_field("message_type", &self.message_type)?; } @@ -4536,6 +4845,8 @@ impl<'de> serde::Deserialize<'de> for FileDescriptorProto { "publicDependency", "weak_dependency", "weakDependency", + "option_dependency", + "optionDependency", "message_type", "messageType", "enum_type", @@ -4556,6 +4867,7 @@ impl<'de> serde::Deserialize<'de> for FileDescriptorProto { Dependency, PublicDependency, WeakDependency, + OptionDependency, MessageType, EnumType, Service, @@ -4590,6 +4902,7 @@ impl<'de> serde::Deserialize<'de> for FileDescriptorProto { "dependency" => Ok(GeneratedField::Dependency), "publicDependency" | "public_dependency" => Ok(GeneratedField::PublicDependency), "weakDependency" | "weak_dependency" => Ok(GeneratedField::WeakDependency), + "optionDependency" | "option_dependency" => Ok(GeneratedField::OptionDependency), "messageType" | "message_type" => Ok(GeneratedField::MessageType), "enumType" | "enum_type" => Ok(GeneratedField::EnumType), "service" => Ok(GeneratedField::Service), @@ -4622,6 +4935,7 @@ impl<'de> serde::Deserialize<'de> for FileDescriptorProto { let mut dependency__ = None; let mut public_dependency__ = None; let mut weak_dependency__ = None; + let mut option_dependency__ = None; let mut message_type__ = None; let mut enum_type__ = None; let mut service__ = None; @@ -4668,6 +4982,12 @@ impl<'de> serde::Deserialize<'de> for FileDescriptorProto { .into_iter().map(|x| x.0).collect()) ; } + GeneratedField::OptionDependency => { + if option_dependency__.is_some() { + return Err(serde::de::Error::duplicate_field("optionDependency")); + } + option_dependency__ = Some(map_.next_value()?); + } GeneratedField::MessageType => { if message_type__.is_some() { return Err(serde::de::Error::duplicate_field("messageType")); @@ -4724,6 +5044,7 @@ impl<'de> serde::Deserialize<'de> for FileDescriptorProto { dependency: dependency__.unwrap_or_default(), public_dependency: public_dependency__.unwrap_or_default(), weak_dependency: weak_dependency__.unwrap_or_default(), + option_dependency: option_dependency__.unwrap_or_default(), message_type: message_type__.unwrap_or_default(), enum_type: enum_type__.unwrap_or_default(), service: service__.unwrap_or_default(), @@ -7638,6 +7959,80 @@ impl<'de> serde::Deserialize<'de> for Struct { deserializer.deserialize_struct("google.protobuf.Struct", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for SymbolVisibility { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + let variant = match self { + Self::VisibilityUnset => "VISIBILITY_UNSET", + Self::VisibilityLocal => "VISIBILITY_LOCAL", + Self::VisibilityExport => "VISIBILITY_EXPORT", + }; + serializer.serialize_str(variant) + } +} +impl<'de> serde::Deserialize<'de> for SymbolVisibility { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "VISIBILITY_UNSET", + "VISIBILITY_LOCAL", + "VISIBILITY_EXPORT", + ]; + + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = SymbolVisibility; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + fn visit_i64(self, v: i64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) + }) + } + + fn visit_u64(self, v: u64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) + }) + } + + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "VISIBILITY_UNSET" => Ok(SymbolVisibility::VisibilityUnset), + "VISIBILITY_LOCAL" => Ok(SymbolVisibility::VisibilityLocal), + "VISIBILITY_EXPORT" => Ok(SymbolVisibility::VisibilityExport), + _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), + } + } + } + deserializer.deserialize_any(GeneratedVisitor) + } +} impl serde::Serialize for Timestamp { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/src/generated/mod.rs b/src/generated/mod.rs index 805b220..66d1c87 100644 --- a/src/generated/mod.rs +++ b/src/generated/mod.rs @@ -336,6 +336,13 @@ pub mod envoy { include!("envoy.service.metrics.v3.serde.rs"); } } + pub mod network_ext_proc { + pub mod v3 { + include!("envoy.service.network_ext_proc.v3.rs"); + #[cfg(feature = "pbjson")] + include!("envoy.service.network_ext_proc.v3.serde.rs"); + } + } pub mod rate_limit_quota { pub mod v3 { include!("envoy.service.rate_limit_quota.v3.rs"); @@ -350,6 +357,13 @@ pub mod envoy { include!("envoy.service.ratelimit.v3.serde.rs"); } } + pub mod redis_auth { + pub mod v3 { + include!("envoy.service.redis_auth.v3.rs"); + #[cfg(feature = "pbjson")] + include!("envoy.service.redis_auth.v3.serde.rs"); + } + } pub mod route { pub mod v3 { include!("envoy.service.route.v3.rs"); @@ -385,13 +399,6 @@ pub mod envoy { include!("envoy.service.tap.v3.serde.rs"); } } - pub mod trace { - pub mod v3 { - include!("envoy.service.trace.v3.rs"); - #[cfg(feature = "pbjson")] - include!("envoy.service.trace.v3.serde.rs"); - } - } } } pub mod google { @@ -427,24 +434,6 @@ pub mod io { } } } -pub mod opencensus { - pub mod proto { - pub mod resource { - pub mod v1 { - include!("opencensus.proto.resource.v1.rs"); - #[cfg(feature = "pbjson")] - include!("opencensus.proto.resource.v1.serde.rs"); - } - } - pub mod trace { - pub mod v1 { - include!("opencensus.proto.trace.v1.rs"); - #[cfg(feature = "pbjson")] - include!("opencensus.proto.trace.v1.serde.rs"); - } - } - } -} pub mod udpa { pub mod annotations { include!("udpa.annotations.rs"); diff --git a/src/generated/opencensus.proto.resource.v1.rs b/src/generated/opencensus.proto.resource.v1.rs deleted file mode 100644 index a2a9d66..0000000 --- a/src/generated/opencensus.proto.resource.v1.rs +++ /dev/null @@ -1,24 +0,0 @@ -// This file is @generated by prost-build. -/// Resource information. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Resource { - /// Type identifier for the resource. - #[prost(string, tag = "1")] - pub r#type: ::prost::alloc::string::String, - /// Set of labels that describe the resource. - #[prost(map = "string, string", tag = "2")] - pub labels: ::std::collections::HashMap< - ::prost::alloc::string::String, - ::prost::alloc::string::String, - >, -} -impl ::prost::Name for Resource { - const NAME: &'static str = "Resource"; - const PACKAGE: &'static str = "opencensus.proto.resource.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.resource.v1.Resource".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.resource.v1.Resource".into() - } -} diff --git a/src/generated/opencensus.proto.resource.v1.serde.rs b/src/generated/opencensus.proto.resource.v1.serde.rs deleted file mode 100644 index 2b9aa08..0000000 --- a/src/generated/opencensus.proto.resource.v1.serde.rs +++ /dev/null @@ -1,110 +0,0 @@ -impl serde::Serialize for Resource { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.r#type.is_empty() { - len += 1; - } - if !self.labels.is_empty() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.resource.v1.Resource", len)?; - if !self.r#type.is_empty() { - struct_ser.serialize_field("type", &self.r#type)?; - } - if !self.labels.is_empty() { - struct_ser.serialize_field("labels", &self.labels)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for Resource { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "type", - "labels", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Type, - Labels, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "type" => Ok(GeneratedField::Type), - "labels" => Ok(GeneratedField::Labels), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = Resource; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.resource.v1.Resource") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut r#type__ = None; - let mut labels__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Type => { - if r#type__.is_some() { - return Err(serde::de::Error::duplicate_field("type")); - } - r#type__ = Some(map_.next_value()?); - } - GeneratedField::Labels => { - if labels__.is_some() { - return Err(serde::de::Error::duplicate_field("labels")); - } - labels__ = Some( - map_.next_value::>()? - ); - } - } - } - Ok(Resource { - r#type: r#type__.unwrap_or_default(), - labels: labels__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("opencensus.proto.resource.v1.Resource", FIELDS, GeneratedVisitor) - } -} diff --git a/src/generated/opencensus.proto.trace.v1.rs b/src/generated/opencensus.proto.trace.v1.rs deleted file mode 100644 index 0f19d19..0000000 --- a/src/generated/opencensus.proto.trace.v1.rs +++ /dev/null @@ -1,871 +0,0 @@ -// This file is @generated by prost-build. -/// Global configuration of the trace service. All fields must be specified, or -/// the default (zero) values will be used for each type. -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct TraceConfig { - /// The global default max number of attributes per span. - #[prost(int64, tag = "4")] - pub max_number_of_attributes: i64, - /// The global default max number of annotation events per span. - #[prost(int64, tag = "5")] - pub max_number_of_annotations: i64, - /// The global default max number of message events per span. - #[prost(int64, tag = "6")] - pub max_number_of_message_events: i64, - /// The global default max number of link entries per span. - #[prost(int64, tag = "7")] - pub max_number_of_links: i64, - /// The global default sampler used to make decisions on span sampling. - #[prost(oneof = "trace_config::Sampler", tags = "1, 2, 3")] - pub sampler: ::core::option::Option, -} -/// Nested message and enum types in `TraceConfig`. -pub mod trace_config { - /// The global default sampler used to make decisions on span sampling. - #[derive(Clone, Copy, PartialEq, ::prost::Oneof)] - pub enum Sampler { - #[prost(message, tag = "1")] - ProbabilitySampler(super::ProbabilitySampler), - #[prost(message, tag = "2")] - ConstantSampler(super::ConstantSampler), - #[prost(message, tag = "3")] - RateLimitingSampler(super::RateLimitingSampler), - } -} -impl ::prost::Name for TraceConfig { - const NAME: &'static str = "TraceConfig"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.TraceConfig".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.TraceConfig".into() - } -} -/// Sampler that tries to uniformly sample traces with a given probability. -/// The probability of sampling a trace is equal to that of the specified probability. -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct ProbabilitySampler { - /// The desired probability of sampling. Must be within \[0.0, 1.0\]. - #[prost(double, tag = "1")] - pub sampling_probability: f64, -} -impl ::prost::Name for ProbabilitySampler { - const NAME: &'static str = "ProbabilitySampler"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.ProbabilitySampler".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.ProbabilitySampler".into() - } -} -/// Sampler that always makes a constant decision on span sampling. -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct ConstantSampler { - #[prost(enumeration = "constant_sampler::ConstantDecision", tag = "1")] - pub decision: i32, -} -/// Nested message and enum types in `ConstantSampler`. -pub mod constant_sampler { - /// How spans should be sampled: - /// - Always off - /// - Always on - /// - Always follow the parent Span's decision (off if no parent). - #[derive( - Clone, - Copy, - Debug, - PartialEq, - Eq, - Hash, - PartialOrd, - Ord, - ::prost::Enumeration - )] - #[repr(i32)] - pub enum ConstantDecision { - AlwaysOff = 0, - AlwaysOn = 1, - AlwaysParent = 2, - } - impl ConstantDecision { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - Self::AlwaysOff => "ALWAYS_OFF", - Self::AlwaysOn => "ALWAYS_ON", - Self::AlwaysParent => "ALWAYS_PARENT", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "ALWAYS_OFF" => Some(Self::AlwaysOff), - "ALWAYS_ON" => Some(Self::AlwaysOn), - "ALWAYS_PARENT" => Some(Self::AlwaysParent), - _ => None, - } - } - } -} -impl ::prost::Name for ConstantSampler { - const NAME: &'static str = "ConstantSampler"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.ConstantSampler".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.ConstantSampler".into() - } -} -/// Sampler that tries to sample with a rate per time window. -#[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct RateLimitingSampler { - /// Rate per second. - #[prost(int64, tag = "1")] - pub qps: i64, -} -impl ::prost::Name for RateLimitingSampler { - const NAME: &'static str = "RateLimitingSampler"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.RateLimitingSampler".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.RateLimitingSampler".into() - } -} -/// A span represents a single operation within a trace. Spans can be -/// nested to form a trace tree. Spans may also be linked to other spans -/// from the same or different trace. And form graphs. Often, a trace -/// contains a root span that describes the end-to-end latency, and one -/// or more subspans for its sub-operations. A trace can also contain -/// multiple root spans, or none at all. Spans do not need to be -/// contiguous - there may be gaps or overlaps between spans in a trace. -/// -/// The next id is 17. -/// TODO(bdrutu): Add an example. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Span { - /// A unique identifier for a trace. All spans from the same trace share - /// the same `trace_id`. The ID is a 16-byte array. An ID with all zeroes - /// is considered invalid. - /// - /// This field is semantically required. Receiver should generate new - /// random trace_id if empty or invalid trace_id was received. - /// - /// This field is required. - #[prost(bytes = "vec", tag = "1")] - pub trace_id: ::prost::alloc::vec::Vec, - /// A unique identifier for a span within a trace, assigned when the span - /// is created. The ID is an 8-byte array. An ID with all zeroes is considered - /// invalid. - /// - /// This field is semantically required. Receiver should generate new - /// random span_id if empty or invalid span_id was received. - /// - /// This field is required. - #[prost(bytes = "vec", tag = "2")] - pub span_id: ::prost::alloc::vec::Vec, - /// The Tracestate on the span. - #[prost(message, optional, tag = "15")] - pub tracestate: ::core::option::Option, - /// The `span_id` of this span's parent span. If this is a root span, then this - /// field must be empty. The ID is an 8-byte array. - #[prost(bytes = "vec", tag = "3")] - pub parent_span_id: ::prost::alloc::vec::Vec, - /// A description of the span's operation. - /// - /// For example, the name can be a qualified method name or a file name - /// and a line number where the operation is called. A best practice is to use - /// the same display name at the same call point in an application. - /// This makes it easier to correlate spans in different traces. - /// - /// This field is semantically required to be set to non-empty string. - /// When null or empty string received - receiver may use string "name" - /// as a replacement. There might be smarted algorithms implemented by - /// receiver to fix the empty span name. - /// - /// This field is required. - #[prost(message, optional, tag = "4")] - pub name: ::core::option::Option, - /// Distinguishes between spans generated in a particular context. For example, - /// two spans with the same name may be distinguished using `CLIENT` (caller) - /// and `SERVER` (callee) to identify queueing latency associated with the span. - #[prost(enumeration = "span::SpanKind", tag = "14")] - pub kind: i32, - /// The start time of the span. On the client side, this is the time kept by - /// the local machine where the span execution starts. On the server side, this - /// is the time when the server's application handler starts running. - /// - /// This field is semantically required. When not set on receive - - /// receiver should set it to the value of end_time field if it was - /// set. Or to the current time if neither was set. It is important to - /// keep end_time > start_time for consistency. - /// - /// This field is required. - #[prost(message, optional, tag = "5")] - pub start_time: ::core::option::Option< - super::super::super::super::google::protobuf::Timestamp, - >, - /// The end time of the span. On the client side, this is the time kept by - /// the local machine where the span execution ends. On the server side, this - /// is the time when the server application handler stops running. - /// - /// This field is semantically required. When not set on receive - - /// receiver should set it to start_time value. It is important to - /// keep end_time > start_time for consistency. - /// - /// This field is required. - #[prost(message, optional, tag = "6")] - pub end_time: ::core::option::Option< - super::super::super::super::google::protobuf::Timestamp, - >, - /// A set of attributes on the span. - #[prost(message, optional, tag = "7")] - pub attributes: ::core::option::Option, - /// A stack trace captured at the start of the span. - #[prost(message, optional, tag = "8")] - pub stack_trace: ::core::option::Option, - /// The included time events. - #[prost(message, optional, tag = "9")] - pub time_events: ::core::option::Option, - /// The included links. - #[prost(message, optional, tag = "10")] - pub links: ::core::option::Option, - /// An optional final status for this span. Semantically when Status - /// wasn't set it is means span ended without errors and assume - /// Status.Ok (code = 0). - #[prost(message, optional, tag = "11")] - pub status: ::core::option::Option, - /// An optional resource that is associated with this span. If not set, this span - /// should be part of a batch that does include the resource information, unless resource - /// information is unknown. - #[prost(message, optional, tag = "16")] - pub resource: ::core::option::Option, - /// A highly recommended but not required flag that identifies when a - /// trace crosses a process boundary. True when the parent_span belongs - /// to the same process as the current span. This flag is most commonly - /// used to indicate the need to adjust time as clocks in different - /// processes may not be synchronized. - #[prost(message, optional, tag = "12")] - pub same_process_as_parent_span: ::core::option::Option< - super::super::super::super::google::protobuf::BoolValue, - >, - /// An optional number of child spans that were generated while this span - /// was active. If set, allows an implementation to detect missing child spans. - #[prost(message, optional, tag = "13")] - pub child_span_count: ::core::option::Option< - super::super::super::super::google::protobuf::UInt32Value, - >, -} -/// Nested message and enum types in `Span`. -pub mod span { - /// This field conveys information about request position in multiple distributed tracing graphs. - /// It is a list of Tracestate.Entry with a maximum of 32 members in the list. - /// - /// See the for more details about this field. - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct Tracestate { - /// A list of entries that represent the Tracestate. - #[prost(message, repeated, tag = "1")] - pub entries: ::prost::alloc::vec::Vec, - } - /// Nested message and enum types in `Tracestate`. - pub mod tracestate { - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct Entry { - /// The key must begin with a lowercase letter, and can only contain - /// lowercase letters 'a'-'z', digits '0'-'9', underscores '_', dashes - /// '-', asterisks '*', and forward slashes '/'. - #[prost(string, tag = "1")] - pub key: ::prost::alloc::string::String, - /// The value is opaque string up to 256 characters printable ASCII - /// RFC0020 characters (i.e., the range 0x20 to 0x7E) except ',' and '='. - /// Note that this also excludes tabs, newlines, carriage returns, etc. - #[prost(string, tag = "2")] - pub value: ::prost::alloc::string::String, - } - impl ::prost::Name for Entry { - const NAME: &'static str = "Entry"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.Span.Tracestate.Entry".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.Span.Tracestate.Entry".into() - } - } - } - impl ::prost::Name for Tracestate { - const NAME: &'static str = "Tracestate"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.Span.Tracestate".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.Span.Tracestate".into() - } - } - /// A set of attributes, each with a key and a value. - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct Attributes { - /// The set of attributes. The value can be a string, an integer, a double - /// or the Boolean values `true` or `false`. Note, global attributes like - /// server name can be set as tags using resource API. Examples of attributes: - /// - /// "/http/user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" - /// "/http/server_latency": 300 - /// "abc.com/myattribute": true - /// "abc.com/score": 10.239 - #[prost(map = "string, message", tag = "1")] - pub attribute_map: ::std::collections::HashMap< - ::prost::alloc::string::String, - super::AttributeValue, - >, - /// The number of attributes that were discarded. Attributes can be discarded - /// because their keys are too long or because there are too many attributes. - /// If this value is 0, then no attributes were dropped. - #[prost(int32, tag = "2")] - pub dropped_attributes_count: i32, - } - impl ::prost::Name for Attributes { - const NAME: &'static str = "Attributes"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.Span.Attributes".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.Span.Attributes".into() - } - } - /// A time-stamped annotation or message event in the Span. - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct TimeEvent { - /// The time the event occurred. - #[prost(message, optional, tag = "1")] - pub time: ::core::option::Option< - super::super::super::super::super::google::protobuf::Timestamp, - >, - /// A `TimeEvent` can contain either an `Annotation` object or a - /// `MessageEvent` object, but not both. - #[prost(oneof = "time_event::Value", tags = "2, 3")] - pub value: ::core::option::Option, - } - /// Nested message and enum types in `TimeEvent`. - pub mod time_event { - /// A text annotation with a set of attributes. - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct Annotation { - /// A user-supplied message describing the event. - #[prost(message, optional, tag = "1")] - pub description: ::core::option::Option, - /// A set of attributes on the annotation. - #[prost(message, optional, tag = "2")] - pub attributes: ::core::option::Option, - } - impl ::prost::Name for Annotation { - const NAME: &'static str = "Annotation"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.Span.TimeEvent.Annotation".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.Span.TimeEvent.Annotation".into() - } - } - /// An event describing a message sent/received between Spans. - #[derive(Clone, Copy, PartialEq, ::prost::Message)] - pub struct MessageEvent { - /// The type of MessageEvent. Indicates whether the message was sent or - /// received. - #[prost(enumeration = "message_event::Type", tag = "1")] - pub r#type: i32, - /// An identifier for the MessageEvent's message that can be used to match - /// SENT and RECEIVED MessageEvents. For example, this field could - /// represent a sequence ID for a streaming RPC. It is recommended to be - /// unique within a Span. - #[prost(uint64, tag = "2")] - pub id: u64, - /// The number of uncompressed bytes sent or received. - #[prost(uint64, tag = "3")] - pub uncompressed_size: u64, - /// The number of compressed bytes sent or received. If zero, assumed to - /// be the same size as uncompressed. - #[prost(uint64, tag = "4")] - pub compressed_size: u64, - } - /// Nested message and enum types in `MessageEvent`. - pub mod message_event { - /// Indicates whether the message was sent or received. - #[derive( - Clone, - Copy, - Debug, - PartialEq, - Eq, - Hash, - PartialOrd, - Ord, - ::prost::Enumeration - )] - #[repr(i32)] - pub enum Type { - /// Unknown event type. - Unspecified = 0, - /// Indicates a sent message. - Sent = 1, - /// Indicates a received message. - Received = 2, - } - impl Type { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - Self::Unspecified => "TYPE_UNSPECIFIED", - Self::Sent => "SENT", - Self::Received => "RECEIVED", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "TYPE_UNSPECIFIED" => Some(Self::Unspecified), - "SENT" => Some(Self::Sent), - "RECEIVED" => Some(Self::Received), - _ => None, - } - } - } - } - impl ::prost::Name for MessageEvent { - const NAME: &'static str = "MessageEvent"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.Span.TimeEvent.MessageEvent".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.Span.TimeEvent.MessageEvent".into() - } - } - /// A `TimeEvent` can contain either an `Annotation` object or a - /// `MessageEvent` object, but not both. - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Value { - /// A text annotation with a set of attributes. - #[prost(message, tag = "2")] - Annotation(Annotation), - /// An event describing a message sent/received between Spans. - #[prost(message, tag = "3")] - MessageEvent(MessageEvent), - } - } - impl ::prost::Name for TimeEvent { - const NAME: &'static str = "TimeEvent"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.Span.TimeEvent".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.Span.TimeEvent".into() - } - } - /// A collection of `TimeEvent`s. A `TimeEvent` is a time-stamped annotation - /// on the span, consisting of either user-supplied key-value pairs, or - /// details of a message sent/received between Spans. - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct TimeEvents { - /// A collection of `TimeEvent`s. - #[prost(message, repeated, tag = "1")] - pub time_event: ::prost::alloc::vec::Vec, - /// The number of dropped annotations in all the included time events. - /// If the value is 0, then no annotations were dropped. - #[prost(int32, tag = "2")] - pub dropped_annotations_count: i32, - /// The number of dropped message events in all the included time events. - /// If the value is 0, then no message events were dropped. - #[prost(int32, tag = "3")] - pub dropped_message_events_count: i32, - } - impl ::prost::Name for TimeEvents { - const NAME: &'static str = "TimeEvents"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.Span.TimeEvents".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.Span.TimeEvents".into() - } - } - /// A pointer from the current span to another span in the same trace or in a - /// different trace. For example, this can be used in batching operations, - /// where a single batch handler processes multiple requests from different - /// traces or when the handler receives a request from a different project. - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct Link { - /// A unique identifier of a trace that this linked span is part of. The ID is a - /// 16-byte array. - #[prost(bytes = "vec", tag = "1")] - pub trace_id: ::prost::alloc::vec::Vec, - /// A unique identifier for the linked span. The ID is an 8-byte array. - #[prost(bytes = "vec", tag = "2")] - pub span_id: ::prost::alloc::vec::Vec, - /// The relationship of the current span relative to the linked span. - #[prost(enumeration = "link::Type", tag = "3")] - pub r#type: i32, - /// A set of attributes on the link. - #[prost(message, optional, tag = "4")] - pub attributes: ::core::option::Option, - /// The Tracestate associated with the link. - #[prost(message, optional, tag = "5")] - pub tracestate: ::core::option::Option, - } - /// Nested message and enum types in `Link`. - pub mod link { - /// The relationship of the current span relative to the linked span: child, - /// parent, or unspecified. - #[derive( - Clone, - Copy, - Debug, - PartialEq, - Eq, - Hash, - PartialOrd, - Ord, - ::prost::Enumeration - )] - #[repr(i32)] - pub enum Type { - /// The relationship of the two spans is unknown, or known but other - /// than parent-child. - Unspecified = 0, - /// The linked span is a child of the current span. - ChildLinkedSpan = 1, - /// The linked span is a parent of the current span. - ParentLinkedSpan = 2, - } - impl Type { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - Self::Unspecified => "TYPE_UNSPECIFIED", - Self::ChildLinkedSpan => "CHILD_LINKED_SPAN", - Self::ParentLinkedSpan => "PARENT_LINKED_SPAN", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "TYPE_UNSPECIFIED" => Some(Self::Unspecified), - "CHILD_LINKED_SPAN" => Some(Self::ChildLinkedSpan), - "PARENT_LINKED_SPAN" => Some(Self::ParentLinkedSpan), - _ => None, - } - } - } - } - impl ::prost::Name for Link { - const NAME: &'static str = "Link"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.Span.Link".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.Span.Link".into() - } - } - /// A collection of links, which are references from this span to a span - /// in the same or different trace. - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct Links { - /// A collection of links. - #[prost(message, repeated, tag = "1")] - pub link: ::prost::alloc::vec::Vec, - /// The number of dropped links after the maximum size was enforced. If - /// this value is 0, then no links were dropped. - #[prost(int32, tag = "2")] - pub dropped_links_count: i32, - } - impl ::prost::Name for Links { - const NAME: &'static str = "Links"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.Span.Links".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.Span.Links".into() - } - } - /// Type of span. Can be used to specify additional relationships between spans - /// in addition to a parent/child relationship. - #[derive( - Clone, - Copy, - Debug, - PartialEq, - Eq, - Hash, - PartialOrd, - Ord, - ::prost::Enumeration - )] - #[repr(i32)] - pub enum SpanKind { - /// Unspecified. - Unspecified = 0, - /// Indicates that the span covers server-side handling of an RPC or other - /// remote network request. - Server = 1, - /// Indicates that the span covers the client-side wrapper around an RPC or - /// other remote request. - Client = 2, - } - impl SpanKind { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - Self::Unspecified => "SPAN_KIND_UNSPECIFIED", - Self::Server => "SERVER", - Self::Client => "CLIENT", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "SPAN_KIND_UNSPECIFIED" => Some(Self::Unspecified), - "SERVER" => Some(Self::Server), - "CLIENT" => Some(Self::Client), - _ => None, - } - } - } -} -impl ::prost::Name for Span { - const NAME: &'static str = "Span"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.Span".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.Span".into() - } -} -/// The `Status` type defines a logical error model that is suitable for different -/// programming environments, including REST APIs and RPC APIs. This proto's fields -/// are a subset of those of -/// [google.rpc.Status](), -/// which is used by [gRPC](). -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Status { - /// The status code. This is optional field. It is safe to assume 0 (OK) - /// when not set. - #[prost(int32, tag = "1")] - pub code: i32, - /// A developer-facing error message, which should be in English. - #[prost(string, tag = "2")] - pub message: ::prost::alloc::string::String, -} -impl ::prost::Name for Status { - const NAME: &'static str = "Status"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.Status".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.Status".into() - } -} -/// The value of an Attribute. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct AttributeValue { - /// The type of the value. - #[prost(oneof = "attribute_value::Value", tags = "1, 2, 3, 4")] - pub value: ::core::option::Option, -} -/// Nested message and enum types in `AttributeValue`. -pub mod attribute_value { - /// The type of the value. - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Value { - /// A string up to 256 bytes long. - #[prost(message, tag = "1")] - StringValue(super::TruncatableString), - /// A 64-bit signed integer. - #[prost(int64, tag = "2")] - IntValue(i64), - /// A Boolean value represented by `true` or `false`. - #[prost(bool, tag = "3")] - BoolValue(bool), - /// A double value. - #[prost(double, tag = "4")] - DoubleValue(f64), - } -} -impl ::prost::Name for AttributeValue { - const NAME: &'static str = "AttributeValue"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.AttributeValue".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.AttributeValue".into() - } -} -/// The call stack which originated this span. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct StackTrace { - /// Stack frames in this stack trace. - #[prost(message, optional, tag = "1")] - pub stack_frames: ::core::option::Option, - /// The hash ID is used to conserve network bandwidth for duplicate - /// stack traces within a single trace. - /// - /// Often multiple spans will have identical stack traces. - /// The first occurrence of a stack trace should contain both - /// `stack_frames` and a value in `stack_trace_hash_id`. - /// - /// Subsequent spans within the same request can refer - /// to that stack trace by setting only `stack_trace_hash_id`. - /// - /// TODO: describe how to deal with the case where stack_trace_hash_id is - /// zero because it was not set. - #[prost(uint64, tag = "2")] - pub stack_trace_hash_id: u64, -} -/// Nested message and enum types in `StackTrace`. -pub mod stack_trace { - /// A single stack frame in a stack trace. - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct StackFrame { - /// The fully-qualified name that uniquely identifies the function or - /// method that is active in this frame. - #[prost(message, optional, tag = "1")] - pub function_name: ::core::option::Option, - /// An un-mangled function name, if `function_name` is - /// [mangled](). The name can - /// be fully qualified. - #[prost(message, optional, tag = "2")] - pub original_function_name: ::core::option::Option, - /// The name of the source file where the function call appears. - #[prost(message, optional, tag = "3")] - pub file_name: ::core::option::Option, - /// The line number in `file_name` where the function call appears. - #[prost(int64, tag = "4")] - pub line_number: i64, - /// The column number where the function call appears, if available. - /// This is important in JavaScript because of its anonymous functions. - #[prost(int64, tag = "5")] - pub column_number: i64, - /// The binary module from where the code was loaded. - #[prost(message, optional, tag = "6")] - pub load_module: ::core::option::Option, - /// The version of the deployed source code. - #[prost(message, optional, tag = "7")] - pub source_version: ::core::option::Option, - } - impl ::prost::Name for StackFrame { - const NAME: &'static str = "StackFrame"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.StackTrace.StackFrame".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.StackTrace.StackFrame".into() - } - } - /// A collection of stack frames, which can be truncated. - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct StackFrames { - /// Stack frames in this call stack. - #[prost(message, repeated, tag = "1")] - pub frame: ::prost::alloc::vec::Vec, - /// The number of stack frames that were dropped because there - /// were too many stack frames. - /// If this value is 0, then no stack frames were dropped. - #[prost(int32, tag = "2")] - pub dropped_frames_count: i32, - } - impl ::prost::Name for StackFrames { - const NAME: &'static str = "StackFrames"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.StackTrace.StackFrames".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.StackTrace.StackFrames".into() - } - } -} -impl ::prost::Name for StackTrace { - const NAME: &'static str = "StackTrace"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.StackTrace".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.StackTrace".into() - } -} -/// A description of a binary module. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Module { - /// TODO: document the meaning of this field. - /// For example: main binary, kernel modules, and dynamic libraries - /// such as libc.so, sharedlib.so. - #[prost(message, optional, tag = "1")] - pub module: ::core::option::Option, - /// A unique identifier for the module, usually a hash of its - /// contents. - #[prost(message, optional, tag = "2")] - pub build_id: ::core::option::Option, -} -impl ::prost::Name for Module { - const NAME: &'static str = "Module"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.Module".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.Module".into() - } -} -/// A string that might be shortened to a specified length. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct TruncatableString { - /// The shortened string. For example, if the original string was 500 bytes long and - /// the limit of the string was 128 bytes, then this value contains the first 128 - /// bytes of the 500-byte string. Note that truncation always happens on a - /// character boundary, to ensure that a truncated string is still valid UTF-8. - /// Because it may contain multi-byte characters, the size of the truncated string - /// may be less than the truncation limit. - #[prost(string, tag = "1")] - pub value: ::prost::alloc::string::String, - /// The number of bytes removed from the original string. If this - /// value is 0, then the string was not shortened. - #[prost(int32, tag = "2")] - pub truncated_byte_count: i32, -} -impl ::prost::Name for TruncatableString { - const NAME: &'static str = "TruncatableString"; - const PACKAGE: &'static str = "opencensus.proto.trace.v1"; - fn full_name() -> ::prost::alloc::string::String { - "opencensus.proto.trace.v1.TruncatableString".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/opencensus.proto.trace.v1.TruncatableString".into() - } -} diff --git a/src/generated/opencensus.proto.trace.v1.serde.rs b/src/generated/opencensus.proto.trace.v1.serde.rs deleted file mode 100644 index ef31fb7..0000000 --- a/src/generated/opencensus.proto.trace.v1.serde.rs +++ /dev/null @@ -1,3180 +0,0 @@ -impl serde::Serialize for AttributeValue { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.value.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.AttributeValue", len)?; - if let Some(v) = self.value.as_ref() { - match v { - attribute_value::Value::StringValue(v) => { - struct_ser.serialize_field("string_value", v)?; - } - attribute_value::Value::IntValue(v) => { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("int_value", ToString::to_string(&v).as_str())?; - } - attribute_value::Value::BoolValue(v) => { - struct_ser.serialize_field("bool_value", v)?; - } - attribute_value::Value::DoubleValue(v) => { - struct_ser.serialize_field("double_value", v)?; - } - } - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for AttributeValue { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "string_value", - "stringValue", - "int_value", - "intValue", - "bool_value", - "boolValue", - "double_value", - "doubleValue", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - StringValue, - IntValue, - BoolValue, - DoubleValue, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "stringValue" | "string_value" => Ok(GeneratedField::StringValue), - "intValue" | "int_value" => Ok(GeneratedField::IntValue), - "boolValue" | "bool_value" => Ok(GeneratedField::BoolValue), - "doubleValue" | "double_value" => Ok(GeneratedField::DoubleValue), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = AttributeValue; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.AttributeValue") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut value__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::StringValue => { - if value__.is_some() { - return Err(serde::de::Error::duplicate_field("stringValue")); - } - value__ = map_.next_value::<::std::option::Option<_>>()?.map(attribute_value::Value::StringValue) -; - } - GeneratedField::IntValue => { - if value__.is_some() { - return Err(serde::de::Error::duplicate_field("intValue")); - } - value__ = map_.next_value::<::std::option::Option<::pbjson::private::NumberDeserialize<_>>>()?.map(|x| attribute_value::Value::IntValue(x.0)); - } - GeneratedField::BoolValue => { - if value__.is_some() { - return Err(serde::de::Error::duplicate_field("boolValue")); - } - value__ = map_.next_value::<::std::option::Option<_>>()?.map(attribute_value::Value::BoolValue); - } - GeneratedField::DoubleValue => { - if value__.is_some() { - return Err(serde::de::Error::duplicate_field("doubleValue")); - } - value__ = map_.next_value::<::std::option::Option<::pbjson::private::NumberDeserialize<_>>>()?.map(|x| attribute_value::Value::DoubleValue(x.0)); - } - } - } - Ok(AttributeValue { - value: value__, - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.AttributeValue", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for ConstantSampler { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.decision != 0 { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.ConstantSampler", len)?; - if self.decision != 0 { - let v = constant_sampler::ConstantDecision::try_from(self.decision) - .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", self.decision)))?; - struct_ser.serialize_field("decision", &v)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for ConstantSampler { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "decision", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Decision, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "decision" => Ok(GeneratedField::Decision), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = ConstantSampler; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.ConstantSampler") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut decision__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Decision => { - if decision__.is_some() { - return Err(serde::de::Error::duplicate_field("decision")); - } - decision__ = Some(map_.next_value::()? as i32); - } - } - } - Ok(ConstantSampler { - decision: decision__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.ConstantSampler", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for constant_sampler::ConstantDecision { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - let variant = match self { - Self::AlwaysOff => "ALWAYS_OFF", - Self::AlwaysOn => "ALWAYS_ON", - Self::AlwaysParent => "ALWAYS_PARENT", - }; - serializer.serialize_str(variant) - } -} -impl<'de> serde::Deserialize<'de> for constant_sampler::ConstantDecision { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "ALWAYS_OFF", - "ALWAYS_ON", - "ALWAYS_PARENT", - ]; - - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = constant_sampler::ConstantDecision; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - fn visit_i64(self, v: i64) -> std::result::Result - where - E: serde::de::Error, - { - i32::try_from(v) - .ok() - .and_then(|x| x.try_into().ok()) - .ok_or_else(|| { - serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) - }) - } - - fn visit_u64(self, v: u64) -> std::result::Result - where - E: serde::de::Error, - { - i32::try_from(v) - .ok() - .and_then(|x| x.try_into().ok()) - .ok_or_else(|| { - serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) - }) - } - - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "ALWAYS_OFF" => Ok(constant_sampler::ConstantDecision::AlwaysOff), - "ALWAYS_ON" => Ok(constant_sampler::ConstantDecision::AlwaysOn), - "ALWAYS_PARENT" => Ok(constant_sampler::ConstantDecision::AlwaysParent), - _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), - } - } - } - deserializer.deserialize_any(GeneratedVisitor) - } -} -impl serde::Serialize for Module { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.module.is_some() { - len += 1; - } - if self.build_id.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.Module", len)?; - if let Some(v) = self.module.as_ref() { - struct_ser.serialize_field("module", v)?; - } - if let Some(v) = self.build_id.as_ref() { - struct_ser.serialize_field("build_id", v)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for Module { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "module", - "build_id", - "buildId", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Module, - BuildId, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "module" => Ok(GeneratedField::Module), - "buildId" | "build_id" => Ok(GeneratedField::BuildId), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = Module; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.Module") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut module__ = None; - let mut build_id__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Module => { - if module__.is_some() { - return Err(serde::de::Error::duplicate_field("module")); - } - module__ = map_.next_value()?; - } - GeneratedField::BuildId => { - if build_id__.is_some() { - return Err(serde::de::Error::duplicate_field("buildId")); - } - build_id__ = map_.next_value()?; - } - } - } - Ok(Module { - module: module__, - build_id: build_id__, - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.Module", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for ProbabilitySampler { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.sampling_probability != 0. { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.ProbabilitySampler", len)?; - if self.sampling_probability != 0. { - struct_ser.serialize_field("samplingProbability", &self.sampling_probability)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for ProbabilitySampler { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "samplingProbability", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - SamplingProbability, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "samplingProbability" => Ok(GeneratedField::SamplingProbability), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = ProbabilitySampler; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.ProbabilitySampler") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut sampling_probability__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::SamplingProbability => { - if sampling_probability__.is_some() { - return Err(serde::de::Error::duplicate_field("samplingProbability")); - } - sampling_probability__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - } - } - Ok(ProbabilitySampler { - sampling_probability: sampling_probability__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.ProbabilitySampler", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for RateLimitingSampler { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.qps != 0 { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.RateLimitingSampler", len)?; - if self.qps != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("qps", ToString::to_string(&self.qps).as_str())?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for RateLimitingSampler { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "qps", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Qps, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "qps" => Ok(GeneratedField::Qps), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = RateLimitingSampler; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.RateLimitingSampler") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut qps__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Qps => { - if qps__.is_some() { - return Err(serde::de::Error::duplicate_field("qps")); - } - qps__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - } - } - Ok(RateLimitingSampler { - qps: qps__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.RateLimitingSampler", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for Span { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.trace_id.is_empty() { - len += 1; - } - if !self.span_id.is_empty() { - len += 1; - } - if self.tracestate.is_some() { - len += 1; - } - if !self.parent_span_id.is_empty() { - len += 1; - } - if self.name.is_some() { - len += 1; - } - if self.kind != 0 { - len += 1; - } - if self.start_time.is_some() { - len += 1; - } - if self.end_time.is_some() { - len += 1; - } - if self.attributes.is_some() { - len += 1; - } - if self.stack_trace.is_some() { - len += 1; - } - if self.time_events.is_some() { - len += 1; - } - if self.links.is_some() { - len += 1; - } - if self.status.is_some() { - len += 1; - } - if self.resource.is_some() { - len += 1; - } - if self.same_process_as_parent_span.is_some() { - len += 1; - } - if self.child_span_count.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.Span", len)?; - if !self.trace_id.is_empty() { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("trace_id", pbjson::private::base64::encode(&self.trace_id).as_str())?; - } - if !self.span_id.is_empty() { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("span_id", pbjson::private::base64::encode(&self.span_id).as_str())?; - } - if let Some(v) = self.tracestate.as_ref() { - struct_ser.serialize_field("tracestate", v)?; - } - if !self.parent_span_id.is_empty() { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("parent_span_id", pbjson::private::base64::encode(&self.parent_span_id).as_str())?; - } - if let Some(v) = self.name.as_ref() { - struct_ser.serialize_field("name", v)?; - } - if self.kind != 0 { - let v = span::SpanKind::try_from(self.kind) - .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", self.kind)))?; - struct_ser.serialize_field("kind", &v)?; - } - if let Some(v) = self.start_time.as_ref() { - struct_ser.serialize_field("start_time", v)?; - } - if let Some(v) = self.end_time.as_ref() { - struct_ser.serialize_field("end_time", v)?; - } - if let Some(v) = self.attributes.as_ref() { - struct_ser.serialize_field("attributes", v)?; - } - if let Some(v) = self.stack_trace.as_ref() { - struct_ser.serialize_field("stack_trace", v)?; - } - if let Some(v) = self.time_events.as_ref() { - struct_ser.serialize_field("time_events", v)?; - } - if let Some(v) = self.links.as_ref() { - struct_ser.serialize_field("links", v)?; - } - if let Some(v) = self.status.as_ref() { - struct_ser.serialize_field("status", v)?; - } - if let Some(v) = self.resource.as_ref() { - struct_ser.serialize_field("resource", v)?; - } - if let Some(v) = self.same_process_as_parent_span.as_ref() { - struct_ser.serialize_field("same_process_as_parent_span", v)?; - } - if let Some(v) = self.child_span_count.as_ref() { - struct_ser.serialize_field("child_span_count", v)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for Span { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "trace_id", - "traceId", - "span_id", - "spanId", - "tracestate", - "parent_span_id", - "parentSpanId", - "name", - "kind", - "start_time", - "startTime", - "end_time", - "endTime", - "attributes", - "stack_trace", - "stackTrace", - "time_events", - "timeEvents", - "links", - "status", - "resource", - "same_process_as_parent_span", - "sameProcessAsParentSpan", - "child_span_count", - "childSpanCount", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - TraceId, - SpanId, - Tracestate, - ParentSpanId, - Name, - Kind, - StartTime, - EndTime, - Attributes, - StackTrace, - TimeEvents, - Links, - Status, - Resource, - SameProcessAsParentSpan, - ChildSpanCount, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "traceId" | "trace_id" => Ok(GeneratedField::TraceId), - "spanId" | "span_id" => Ok(GeneratedField::SpanId), - "tracestate" => Ok(GeneratedField::Tracestate), - "parentSpanId" | "parent_span_id" => Ok(GeneratedField::ParentSpanId), - "name" => Ok(GeneratedField::Name), - "kind" => Ok(GeneratedField::Kind), - "startTime" | "start_time" => Ok(GeneratedField::StartTime), - "endTime" | "end_time" => Ok(GeneratedField::EndTime), - "attributes" => Ok(GeneratedField::Attributes), - "stackTrace" | "stack_trace" => Ok(GeneratedField::StackTrace), - "timeEvents" | "time_events" => Ok(GeneratedField::TimeEvents), - "links" => Ok(GeneratedField::Links), - "status" => Ok(GeneratedField::Status), - "resource" => Ok(GeneratedField::Resource), - "sameProcessAsParentSpan" | "same_process_as_parent_span" => Ok(GeneratedField::SameProcessAsParentSpan), - "childSpanCount" | "child_span_count" => Ok(GeneratedField::ChildSpanCount), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = Span; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.Span") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut trace_id__ = None; - let mut span_id__ = None; - let mut tracestate__ = None; - let mut parent_span_id__ = None; - let mut name__ = None; - let mut kind__ = None; - let mut start_time__ = None; - let mut end_time__ = None; - let mut attributes__ = None; - let mut stack_trace__ = None; - let mut time_events__ = None; - let mut links__ = None; - let mut status__ = None; - let mut resource__ = None; - let mut same_process_as_parent_span__ = None; - let mut child_span_count__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::TraceId => { - if trace_id__.is_some() { - return Err(serde::de::Error::duplicate_field("traceId")); - } - trace_id__ = - Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) - ; - } - GeneratedField::SpanId => { - if span_id__.is_some() { - return Err(serde::de::Error::duplicate_field("spanId")); - } - span_id__ = - Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) - ; - } - GeneratedField::Tracestate => { - if tracestate__.is_some() { - return Err(serde::de::Error::duplicate_field("tracestate")); - } - tracestate__ = map_.next_value()?; - } - GeneratedField::ParentSpanId => { - if parent_span_id__.is_some() { - return Err(serde::de::Error::duplicate_field("parentSpanId")); - } - parent_span_id__ = - Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) - ; - } - GeneratedField::Name => { - if name__.is_some() { - return Err(serde::de::Error::duplicate_field("name")); - } - name__ = map_.next_value()?; - } - GeneratedField::Kind => { - if kind__.is_some() { - return Err(serde::de::Error::duplicate_field("kind")); - } - kind__ = Some(map_.next_value::()? as i32); - } - GeneratedField::StartTime => { - if start_time__.is_some() { - return Err(serde::de::Error::duplicate_field("startTime")); - } - start_time__ = map_.next_value()?; - } - GeneratedField::EndTime => { - if end_time__.is_some() { - return Err(serde::de::Error::duplicate_field("endTime")); - } - end_time__ = map_.next_value()?; - } - GeneratedField::Attributes => { - if attributes__.is_some() { - return Err(serde::de::Error::duplicate_field("attributes")); - } - attributes__ = map_.next_value()?; - } - GeneratedField::StackTrace => { - if stack_trace__.is_some() { - return Err(serde::de::Error::duplicate_field("stackTrace")); - } - stack_trace__ = map_.next_value()?; - } - GeneratedField::TimeEvents => { - if time_events__.is_some() { - return Err(serde::de::Error::duplicate_field("timeEvents")); - } - time_events__ = map_.next_value()?; - } - GeneratedField::Links => { - if links__.is_some() { - return Err(serde::de::Error::duplicate_field("links")); - } - links__ = map_.next_value()?; - } - GeneratedField::Status => { - if status__.is_some() { - return Err(serde::de::Error::duplicate_field("status")); - } - status__ = map_.next_value()?; - } - GeneratedField::Resource => { - if resource__.is_some() { - return Err(serde::de::Error::duplicate_field("resource")); - } - resource__ = map_.next_value()?; - } - GeneratedField::SameProcessAsParentSpan => { - if same_process_as_parent_span__.is_some() { - return Err(serde::de::Error::duplicate_field("sameProcessAsParentSpan")); - } - same_process_as_parent_span__ = map_.next_value()?; - } - GeneratedField::ChildSpanCount => { - if child_span_count__.is_some() { - return Err(serde::de::Error::duplicate_field("childSpanCount")); - } - child_span_count__ = map_.next_value()?; - } - } - } - Ok(Span { - trace_id: trace_id__.unwrap_or_default(), - span_id: span_id__.unwrap_or_default(), - tracestate: tracestate__, - parent_span_id: parent_span_id__.unwrap_or_default(), - name: name__, - kind: kind__.unwrap_or_default(), - start_time: start_time__, - end_time: end_time__, - attributes: attributes__, - stack_trace: stack_trace__, - time_events: time_events__, - links: links__, - status: status__, - resource: resource__, - same_process_as_parent_span: same_process_as_parent_span__, - child_span_count: child_span_count__, - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.Span", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for span::Attributes { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.attribute_map.is_empty() { - len += 1; - } - if self.dropped_attributes_count != 0 { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.Span.Attributes", len)?; - if !self.attribute_map.is_empty() { - struct_ser.serialize_field("attribute_map", &self.attribute_map)?; - } - if self.dropped_attributes_count != 0 { - struct_ser.serialize_field("dropped_attributes_count", &self.dropped_attributes_count)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for span::Attributes { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "attribute_map", - "attributeMap", - "dropped_attributes_count", - "droppedAttributesCount", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - AttributeMap, - DroppedAttributesCount, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "attributeMap" | "attribute_map" => Ok(GeneratedField::AttributeMap), - "droppedAttributesCount" | "dropped_attributes_count" => Ok(GeneratedField::DroppedAttributesCount), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = span::Attributes; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.Span.Attributes") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut attribute_map__ = None; - let mut dropped_attributes_count__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::AttributeMap => { - if attribute_map__.is_some() { - return Err(serde::de::Error::duplicate_field("attributeMap")); - } - attribute_map__ = Some( - map_.next_value::>()? - ); - } - GeneratedField::DroppedAttributesCount => { - if dropped_attributes_count__.is_some() { - return Err(serde::de::Error::duplicate_field("droppedAttributesCount")); - } - dropped_attributes_count__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - } - } - Ok(span::Attributes { - attribute_map: attribute_map__.unwrap_or_default(), - dropped_attributes_count: dropped_attributes_count__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.Span.Attributes", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for span::Link { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.trace_id.is_empty() { - len += 1; - } - if !self.span_id.is_empty() { - len += 1; - } - if self.r#type != 0 { - len += 1; - } - if self.attributes.is_some() { - len += 1; - } - if self.tracestate.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.Span.Link", len)?; - if !self.trace_id.is_empty() { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("trace_id", pbjson::private::base64::encode(&self.trace_id).as_str())?; - } - if !self.span_id.is_empty() { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("span_id", pbjson::private::base64::encode(&self.span_id).as_str())?; - } - if self.r#type != 0 { - let v = span::link::Type::try_from(self.r#type) - .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", self.r#type)))?; - struct_ser.serialize_field("type", &v)?; - } - if let Some(v) = self.attributes.as_ref() { - struct_ser.serialize_field("attributes", v)?; - } - if let Some(v) = self.tracestate.as_ref() { - struct_ser.serialize_field("tracestate", v)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for span::Link { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "trace_id", - "traceId", - "span_id", - "spanId", - "type", - "attributes", - "tracestate", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - TraceId, - SpanId, - Type, - Attributes, - Tracestate, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "traceId" | "trace_id" => Ok(GeneratedField::TraceId), - "spanId" | "span_id" => Ok(GeneratedField::SpanId), - "type" => Ok(GeneratedField::Type), - "attributes" => Ok(GeneratedField::Attributes), - "tracestate" => Ok(GeneratedField::Tracestate), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = span::Link; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.Span.Link") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut trace_id__ = None; - let mut span_id__ = None; - let mut r#type__ = None; - let mut attributes__ = None; - let mut tracestate__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::TraceId => { - if trace_id__.is_some() { - return Err(serde::de::Error::duplicate_field("traceId")); - } - trace_id__ = - Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) - ; - } - GeneratedField::SpanId => { - if span_id__.is_some() { - return Err(serde::de::Error::duplicate_field("spanId")); - } - span_id__ = - Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) - ; - } - GeneratedField::Type => { - if r#type__.is_some() { - return Err(serde::de::Error::duplicate_field("type")); - } - r#type__ = Some(map_.next_value::()? as i32); - } - GeneratedField::Attributes => { - if attributes__.is_some() { - return Err(serde::de::Error::duplicate_field("attributes")); - } - attributes__ = map_.next_value()?; - } - GeneratedField::Tracestate => { - if tracestate__.is_some() { - return Err(serde::de::Error::duplicate_field("tracestate")); - } - tracestate__ = map_.next_value()?; - } - } - } - Ok(span::Link { - trace_id: trace_id__.unwrap_or_default(), - span_id: span_id__.unwrap_or_default(), - r#type: r#type__.unwrap_or_default(), - attributes: attributes__, - tracestate: tracestate__, - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.Span.Link", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for span::link::Type { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - let variant = match self { - Self::Unspecified => "TYPE_UNSPECIFIED", - Self::ChildLinkedSpan => "CHILD_LINKED_SPAN", - Self::ParentLinkedSpan => "PARENT_LINKED_SPAN", - }; - serializer.serialize_str(variant) - } -} -impl<'de> serde::Deserialize<'de> for span::link::Type { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "TYPE_UNSPECIFIED", - "CHILD_LINKED_SPAN", - "PARENT_LINKED_SPAN", - ]; - - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = span::link::Type; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - fn visit_i64(self, v: i64) -> std::result::Result - where - E: serde::de::Error, - { - i32::try_from(v) - .ok() - .and_then(|x| x.try_into().ok()) - .ok_or_else(|| { - serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) - }) - } - - fn visit_u64(self, v: u64) -> std::result::Result - where - E: serde::de::Error, - { - i32::try_from(v) - .ok() - .and_then(|x| x.try_into().ok()) - .ok_or_else(|| { - serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) - }) - } - - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "TYPE_UNSPECIFIED" => Ok(span::link::Type::Unspecified), - "CHILD_LINKED_SPAN" => Ok(span::link::Type::ChildLinkedSpan), - "PARENT_LINKED_SPAN" => Ok(span::link::Type::ParentLinkedSpan), - _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), - } - } - } - deserializer.deserialize_any(GeneratedVisitor) - } -} -impl serde::Serialize for span::Links { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.link.is_empty() { - len += 1; - } - if self.dropped_links_count != 0 { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.Span.Links", len)?; - if !self.link.is_empty() { - struct_ser.serialize_field("link", &self.link)?; - } - if self.dropped_links_count != 0 { - struct_ser.serialize_field("dropped_links_count", &self.dropped_links_count)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for span::Links { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "link", - "dropped_links_count", - "droppedLinksCount", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Link, - DroppedLinksCount, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "link" => Ok(GeneratedField::Link), - "droppedLinksCount" | "dropped_links_count" => Ok(GeneratedField::DroppedLinksCount), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = span::Links; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.Span.Links") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut link__ = None; - let mut dropped_links_count__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Link => { - if link__.is_some() { - return Err(serde::de::Error::duplicate_field("link")); - } - link__ = Some(map_.next_value()?); - } - GeneratedField::DroppedLinksCount => { - if dropped_links_count__.is_some() { - return Err(serde::de::Error::duplicate_field("droppedLinksCount")); - } - dropped_links_count__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - } - } - Ok(span::Links { - link: link__.unwrap_or_default(), - dropped_links_count: dropped_links_count__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.Span.Links", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for span::SpanKind { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - let variant = match self { - Self::Unspecified => "SPAN_KIND_UNSPECIFIED", - Self::Server => "SERVER", - Self::Client => "CLIENT", - }; - serializer.serialize_str(variant) - } -} -impl<'de> serde::Deserialize<'de> for span::SpanKind { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "SPAN_KIND_UNSPECIFIED", - "SERVER", - "CLIENT", - ]; - - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = span::SpanKind; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - fn visit_i64(self, v: i64) -> std::result::Result - where - E: serde::de::Error, - { - i32::try_from(v) - .ok() - .and_then(|x| x.try_into().ok()) - .ok_or_else(|| { - serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) - }) - } - - fn visit_u64(self, v: u64) -> std::result::Result - where - E: serde::de::Error, - { - i32::try_from(v) - .ok() - .and_then(|x| x.try_into().ok()) - .ok_or_else(|| { - serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) - }) - } - - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "SPAN_KIND_UNSPECIFIED" => Ok(span::SpanKind::Unspecified), - "SERVER" => Ok(span::SpanKind::Server), - "CLIENT" => Ok(span::SpanKind::Client), - _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), - } - } - } - deserializer.deserialize_any(GeneratedVisitor) - } -} -impl serde::Serialize for span::TimeEvent { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.time.is_some() { - len += 1; - } - if self.value.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.Span.TimeEvent", len)?; - if let Some(v) = self.time.as_ref() { - struct_ser.serialize_field("time", v)?; - } - if let Some(v) = self.value.as_ref() { - match v { - span::time_event::Value::Annotation(v) => { - struct_ser.serialize_field("annotation", v)?; - } - span::time_event::Value::MessageEvent(v) => { - struct_ser.serialize_field("message_event", v)?; - } - } - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for span::TimeEvent { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "time", - "annotation", - "message_event", - "messageEvent", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Time, - Annotation, - MessageEvent, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "time" => Ok(GeneratedField::Time), - "annotation" => Ok(GeneratedField::Annotation), - "messageEvent" | "message_event" => Ok(GeneratedField::MessageEvent), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = span::TimeEvent; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.Span.TimeEvent") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut time__ = None; - let mut value__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Time => { - if time__.is_some() { - return Err(serde::de::Error::duplicate_field("time")); - } - time__ = map_.next_value()?; - } - GeneratedField::Annotation => { - if value__.is_some() { - return Err(serde::de::Error::duplicate_field("annotation")); - } - value__ = map_.next_value::<::std::option::Option<_>>()?.map(span::time_event::Value::Annotation) -; - } - GeneratedField::MessageEvent => { - if value__.is_some() { - return Err(serde::de::Error::duplicate_field("messageEvent")); - } - value__ = map_.next_value::<::std::option::Option<_>>()?.map(span::time_event::Value::MessageEvent) -; - } - } - } - Ok(span::TimeEvent { - time: time__, - value: value__, - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.Span.TimeEvent", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for span::time_event::Annotation { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.description.is_some() { - len += 1; - } - if self.attributes.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.Span.TimeEvent.Annotation", len)?; - if let Some(v) = self.description.as_ref() { - struct_ser.serialize_field("description", v)?; - } - if let Some(v) = self.attributes.as_ref() { - struct_ser.serialize_field("attributes", v)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for span::time_event::Annotation { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "description", - "attributes", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Description, - Attributes, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "description" => Ok(GeneratedField::Description), - "attributes" => Ok(GeneratedField::Attributes), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = span::time_event::Annotation; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.Span.TimeEvent.Annotation") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut description__ = None; - let mut attributes__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Description => { - if description__.is_some() { - return Err(serde::de::Error::duplicate_field("description")); - } - description__ = map_.next_value()?; - } - GeneratedField::Attributes => { - if attributes__.is_some() { - return Err(serde::de::Error::duplicate_field("attributes")); - } - attributes__ = map_.next_value()?; - } - } - } - Ok(span::time_event::Annotation { - description: description__, - attributes: attributes__, - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.Span.TimeEvent.Annotation", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for span::time_event::MessageEvent { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.r#type != 0 { - len += 1; - } - if self.id != 0 { - len += 1; - } - if self.uncompressed_size != 0 { - len += 1; - } - if self.compressed_size != 0 { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.Span.TimeEvent.MessageEvent", len)?; - if self.r#type != 0 { - let v = span::time_event::message_event::Type::try_from(self.r#type) - .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", self.r#type)))?; - struct_ser.serialize_field("type", &v)?; - } - if self.id != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("id", ToString::to_string(&self.id).as_str())?; - } - if self.uncompressed_size != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("uncompressed_size", ToString::to_string(&self.uncompressed_size).as_str())?; - } - if self.compressed_size != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("compressed_size", ToString::to_string(&self.compressed_size).as_str())?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for span::time_event::MessageEvent { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "type", - "id", - "uncompressed_size", - "uncompressedSize", - "compressed_size", - "compressedSize", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Type, - Id, - UncompressedSize, - CompressedSize, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "type" => Ok(GeneratedField::Type), - "id" => Ok(GeneratedField::Id), - "uncompressedSize" | "uncompressed_size" => Ok(GeneratedField::UncompressedSize), - "compressedSize" | "compressed_size" => Ok(GeneratedField::CompressedSize), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = span::time_event::MessageEvent; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.Span.TimeEvent.MessageEvent") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut r#type__ = None; - let mut id__ = None; - let mut uncompressed_size__ = None; - let mut compressed_size__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Type => { - if r#type__.is_some() { - return Err(serde::de::Error::duplicate_field("type")); - } - r#type__ = Some(map_.next_value::()? as i32); - } - GeneratedField::Id => { - if id__.is_some() { - return Err(serde::de::Error::duplicate_field("id")); - } - id__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - GeneratedField::UncompressedSize => { - if uncompressed_size__.is_some() { - return Err(serde::de::Error::duplicate_field("uncompressedSize")); - } - uncompressed_size__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - GeneratedField::CompressedSize => { - if compressed_size__.is_some() { - return Err(serde::de::Error::duplicate_field("compressedSize")); - } - compressed_size__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - } - } - Ok(span::time_event::MessageEvent { - r#type: r#type__.unwrap_or_default(), - id: id__.unwrap_or_default(), - uncompressed_size: uncompressed_size__.unwrap_or_default(), - compressed_size: compressed_size__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.Span.TimeEvent.MessageEvent", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for span::time_event::message_event::Type { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - let variant = match self { - Self::Unspecified => "TYPE_UNSPECIFIED", - Self::Sent => "SENT", - Self::Received => "RECEIVED", - }; - serializer.serialize_str(variant) - } -} -impl<'de> serde::Deserialize<'de> for span::time_event::message_event::Type { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "TYPE_UNSPECIFIED", - "SENT", - "RECEIVED", - ]; - - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = span::time_event::message_event::Type; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - fn visit_i64(self, v: i64) -> std::result::Result - where - E: serde::de::Error, - { - i32::try_from(v) - .ok() - .and_then(|x| x.try_into().ok()) - .ok_or_else(|| { - serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) - }) - } - - fn visit_u64(self, v: u64) -> std::result::Result - where - E: serde::de::Error, - { - i32::try_from(v) - .ok() - .and_then(|x| x.try_into().ok()) - .ok_or_else(|| { - serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) - }) - } - - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "TYPE_UNSPECIFIED" => Ok(span::time_event::message_event::Type::Unspecified), - "SENT" => Ok(span::time_event::message_event::Type::Sent), - "RECEIVED" => Ok(span::time_event::message_event::Type::Received), - _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), - } - } - } - deserializer.deserialize_any(GeneratedVisitor) - } -} -impl serde::Serialize for span::TimeEvents { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.time_event.is_empty() { - len += 1; - } - if self.dropped_annotations_count != 0 { - len += 1; - } - if self.dropped_message_events_count != 0 { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.Span.TimeEvents", len)?; - if !self.time_event.is_empty() { - struct_ser.serialize_field("time_event", &self.time_event)?; - } - if self.dropped_annotations_count != 0 { - struct_ser.serialize_field("dropped_annotations_count", &self.dropped_annotations_count)?; - } - if self.dropped_message_events_count != 0 { - struct_ser.serialize_field("dropped_message_events_count", &self.dropped_message_events_count)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for span::TimeEvents { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "time_event", - "timeEvent", - "dropped_annotations_count", - "droppedAnnotationsCount", - "dropped_message_events_count", - "droppedMessageEventsCount", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - TimeEvent, - DroppedAnnotationsCount, - DroppedMessageEventsCount, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "timeEvent" | "time_event" => Ok(GeneratedField::TimeEvent), - "droppedAnnotationsCount" | "dropped_annotations_count" => Ok(GeneratedField::DroppedAnnotationsCount), - "droppedMessageEventsCount" | "dropped_message_events_count" => Ok(GeneratedField::DroppedMessageEventsCount), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = span::TimeEvents; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.Span.TimeEvents") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut time_event__ = None; - let mut dropped_annotations_count__ = None; - let mut dropped_message_events_count__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::TimeEvent => { - if time_event__.is_some() { - return Err(serde::de::Error::duplicate_field("timeEvent")); - } - time_event__ = Some(map_.next_value()?); - } - GeneratedField::DroppedAnnotationsCount => { - if dropped_annotations_count__.is_some() { - return Err(serde::de::Error::duplicate_field("droppedAnnotationsCount")); - } - dropped_annotations_count__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - GeneratedField::DroppedMessageEventsCount => { - if dropped_message_events_count__.is_some() { - return Err(serde::de::Error::duplicate_field("droppedMessageEventsCount")); - } - dropped_message_events_count__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - } - } - Ok(span::TimeEvents { - time_event: time_event__.unwrap_or_default(), - dropped_annotations_count: dropped_annotations_count__.unwrap_or_default(), - dropped_message_events_count: dropped_message_events_count__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.Span.TimeEvents", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for span::Tracestate { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.entries.is_empty() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.Span.Tracestate", len)?; - if !self.entries.is_empty() { - struct_ser.serialize_field("entries", &self.entries)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for span::Tracestate { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "entries", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Entries, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "entries" => Ok(GeneratedField::Entries), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = span::Tracestate; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.Span.Tracestate") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut entries__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Entries => { - if entries__.is_some() { - return Err(serde::de::Error::duplicate_field("entries")); - } - entries__ = Some(map_.next_value()?); - } - } - } - Ok(span::Tracestate { - entries: entries__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.Span.Tracestate", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for span::tracestate::Entry { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.key.is_empty() { - len += 1; - } - if !self.value.is_empty() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.Span.Tracestate.Entry", len)?; - if !self.key.is_empty() { - struct_ser.serialize_field("key", &self.key)?; - } - if !self.value.is_empty() { - struct_ser.serialize_field("value", &self.value)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for span::tracestate::Entry { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "key", - "value", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Key, - Value, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "key" => Ok(GeneratedField::Key), - "value" => Ok(GeneratedField::Value), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = span::tracestate::Entry; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.Span.Tracestate.Entry") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut key__ = None; - let mut value__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Key => { - if key__.is_some() { - return Err(serde::de::Error::duplicate_field("key")); - } - key__ = Some(map_.next_value()?); - } - GeneratedField::Value => { - if value__.is_some() { - return Err(serde::de::Error::duplicate_field("value")); - } - value__ = Some(map_.next_value()?); - } - } - } - Ok(span::tracestate::Entry { - key: key__.unwrap_or_default(), - value: value__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.Span.Tracestate.Entry", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for StackTrace { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.stack_frames.is_some() { - len += 1; - } - if self.stack_trace_hash_id != 0 { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.StackTrace", len)?; - if let Some(v) = self.stack_frames.as_ref() { - struct_ser.serialize_field("stack_frames", v)?; - } - if self.stack_trace_hash_id != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("stack_trace_hash_id", ToString::to_string(&self.stack_trace_hash_id).as_str())?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for StackTrace { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "stack_frames", - "stackFrames", - "stack_trace_hash_id", - "stackTraceHashId", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - StackFrames, - StackTraceHashId, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "stackFrames" | "stack_frames" => Ok(GeneratedField::StackFrames), - "stackTraceHashId" | "stack_trace_hash_id" => Ok(GeneratedField::StackTraceHashId), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = StackTrace; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.StackTrace") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut stack_frames__ = None; - let mut stack_trace_hash_id__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::StackFrames => { - if stack_frames__.is_some() { - return Err(serde::de::Error::duplicate_field("stackFrames")); - } - stack_frames__ = map_.next_value()?; - } - GeneratedField::StackTraceHashId => { - if stack_trace_hash_id__.is_some() { - return Err(serde::de::Error::duplicate_field("stackTraceHashId")); - } - stack_trace_hash_id__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - } - } - Ok(StackTrace { - stack_frames: stack_frames__, - stack_trace_hash_id: stack_trace_hash_id__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.StackTrace", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for stack_trace::StackFrame { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.function_name.is_some() { - len += 1; - } - if self.original_function_name.is_some() { - len += 1; - } - if self.file_name.is_some() { - len += 1; - } - if self.line_number != 0 { - len += 1; - } - if self.column_number != 0 { - len += 1; - } - if self.load_module.is_some() { - len += 1; - } - if self.source_version.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.StackTrace.StackFrame", len)?; - if let Some(v) = self.function_name.as_ref() { - struct_ser.serialize_field("function_name", v)?; - } - if let Some(v) = self.original_function_name.as_ref() { - struct_ser.serialize_field("original_function_name", v)?; - } - if let Some(v) = self.file_name.as_ref() { - struct_ser.serialize_field("file_name", v)?; - } - if self.line_number != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("line_number", ToString::to_string(&self.line_number).as_str())?; - } - if self.column_number != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("column_number", ToString::to_string(&self.column_number).as_str())?; - } - if let Some(v) = self.load_module.as_ref() { - struct_ser.serialize_field("load_module", v)?; - } - if let Some(v) = self.source_version.as_ref() { - struct_ser.serialize_field("source_version", v)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for stack_trace::StackFrame { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "function_name", - "functionName", - "original_function_name", - "originalFunctionName", - "file_name", - "fileName", - "line_number", - "lineNumber", - "column_number", - "columnNumber", - "load_module", - "loadModule", - "source_version", - "sourceVersion", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - FunctionName, - OriginalFunctionName, - FileName, - LineNumber, - ColumnNumber, - LoadModule, - SourceVersion, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "functionName" | "function_name" => Ok(GeneratedField::FunctionName), - "originalFunctionName" | "original_function_name" => Ok(GeneratedField::OriginalFunctionName), - "fileName" | "file_name" => Ok(GeneratedField::FileName), - "lineNumber" | "line_number" => Ok(GeneratedField::LineNumber), - "columnNumber" | "column_number" => Ok(GeneratedField::ColumnNumber), - "loadModule" | "load_module" => Ok(GeneratedField::LoadModule), - "sourceVersion" | "source_version" => Ok(GeneratedField::SourceVersion), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = stack_trace::StackFrame; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.StackTrace.StackFrame") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut function_name__ = None; - let mut original_function_name__ = None; - let mut file_name__ = None; - let mut line_number__ = None; - let mut column_number__ = None; - let mut load_module__ = None; - let mut source_version__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::FunctionName => { - if function_name__.is_some() { - return Err(serde::de::Error::duplicate_field("functionName")); - } - function_name__ = map_.next_value()?; - } - GeneratedField::OriginalFunctionName => { - if original_function_name__.is_some() { - return Err(serde::de::Error::duplicate_field("originalFunctionName")); - } - original_function_name__ = map_.next_value()?; - } - GeneratedField::FileName => { - if file_name__.is_some() { - return Err(serde::de::Error::duplicate_field("fileName")); - } - file_name__ = map_.next_value()?; - } - GeneratedField::LineNumber => { - if line_number__.is_some() { - return Err(serde::de::Error::duplicate_field("lineNumber")); - } - line_number__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - GeneratedField::ColumnNumber => { - if column_number__.is_some() { - return Err(serde::de::Error::duplicate_field("columnNumber")); - } - column_number__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - GeneratedField::LoadModule => { - if load_module__.is_some() { - return Err(serde::de::Error::duplicate_field("loadModule")); - } - load_module__ = map_.next_value()?; - } - GeneratedField::SourceVersion => { - if source_version__.is_some() { - return Err(serde::de::Error::duplicate_field("sourceVersion")); - } - source_version__ = map_.next_value()?; - } - } - } - Ok(stack_trace::StackFrame { - function_name: function_name__, - original_function_name: original_function_name__, - file_name: file_name__, - line_number: line_number__.unwrap_or_default(), - column_number: column_number__.unwrap_or_default(), - load_module: load_module__, - source_version: source_version__, - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.StackTrace.StackFrame", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for stack_trace::StackFrames { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.frame.is_empty() { - len += 1; - } - if self.dropped_frames_count != 0 { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.StackTrace.StackFrames", len)?; - if !self.frame.is_empty() { - struct_ser.serialize_field("frame", &self.frame)?; - } - if self.dropped_frames_count != 0 { - struct_ser.serialize_field("dropped_frames_count", &self.dropped_frames_count)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for stack_trace::StackFrames { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "frame", - "dropped_frames_count", - "droppedFramesCount", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Frame, - DroppedFramesCount, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "frame" => Ok(GeneratedField::Frame), - "droppedFramesCount" | "dropped_frames_count" => Ok(GeneratedField::DroppedFramesCount), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = stack_trace::StackFrames; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.StackTrace.StackFrames") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut frame__ = None; - let mut dropped_frames_count__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Frame => { - if frame__.is_some() { - return Err(serde::de::Error::duplicate_field("frame")); - } - frame__ = Some(map_.next_value()?); - } - GeneratedField::DroppedFramesCount => { - if dropped_frames_count__.is_some() { - return Err(serde::de::Error::duplicate_field("droppedFramesCount")); - } - dropped_frames_count__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - } - } - Ok(stack_trace::StackFrames { - frame: frame__.unwrap_or_default(), - dropped_frames_count: dropped_frames_count__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.StackTrace.StackFrames", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for Status { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.code != 0 { - len += 1; - } - if !self.message.is_empty() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.Status", len)?; - if self.code != 0 { - struct_ser.serialize_field("code", &self.code)?; - } - if !self.message.is_empty() { - struct_ser.serialize_field("message", &self.message)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for Status { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "code", - "message", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Code, - Message, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "code" => Ok(GeneratedField::Code), - "message" => Ok(GeneratedField::Message), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = Status; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.Status") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut code__ = None; - let mut message__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Code => { - if code__.is_some() { - return Err(serde::de::Error::duplicate_field("code")); - } - code__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - GeneratedField::Message => { - if message__.is_some() { - return Err(serde::de::Error::duplicate_field("message")); - } - message__ = Some(map_.next_value()?); - } - } - } - Ok(Status { - code: code__.unwrap_or_default(), - message: message__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.Status", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for TraceConfig { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.max_number_of_attributes != 0 { - len += 1; - } - if self.max_number_of_annotations != 0 { - len += 1; - } - if self.max_number_of_message_events != 0 { - len += 1; - } - if self.max_number_of_links != 0 { - len += 1; - } - if self.sampler.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.TraceConfig", len)?; - if self.max_number_of_attributes != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("max_number_of_attributes", ToString::to_string(&self.max_number_of_attributes).as_str())?; - } - if self.max_number_of_annotations != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("max_number_of_annotations", ToString::to_string(&self.max_number_of_annotations).as_str())?; - } - if self.max_number_of_message_events != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("max_number_of_message_events", ToString::to_string(&self.max_number_of_message_events).as_str())?; - } - if self.max_number_of_links != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("max_number_of_links", ToString::to_string(&self.max_number_of_links).as_str())?; - } - if let Some(v) = self.sampler.as_ref() { - match v { - trace_config::Sampler::ProbabilitySampler(v) => { - struct_ser.serialize_field("probability_sampler", v)?; - } - trace_config::Sampler::ConstantSampler(v) => { - struct_ser.serialize_field("constant_sampler", v)?; - } - trace_config::Sampler::RateLimitingSampler(v) => { - struct_ser.serialize_field("rate_limiting_sampler", v)?; - } - } - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for TraceConfig { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "max_number_of_attributes", - "maxNumberOfAttributes", - "max_number_of_annotations", - "maxNumberOfAnnotations", - "max_number_of_message_events", - "maxNumberOfMessageEvents", - "max_number_of_links", - "maxNumberOfLinks", - "probability_sampler", - "probabilitySampler", - "constant_sampler", - "constantSampler", - "rate_limiting_sampler", - "rateLimitingSampler", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - MaxNumberOfAttributes, - MaxNumberOfAnnotations, - MaxNumberOfMessageEvents, - MaxNumberOfLinks, - ProbabilitySampler, - ConstantSampler, - RateLimitingSampler, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "maxNumberOfAttributes" | "max_number_of_attributes" => Ok(GeneratedField::MaxNumberOfAttributes), - "maxNumberOfAnnotations" | "max_number_of_annotations" => Ok(GeneratedField::MaxNumberOfAnnotations), - "maxNumberOfMessageEvents" | "max_number_of_message_events" => Ok(GeneratedField::MaxNumberOfMessageEvents), - "maxNumberOfLinks" | "max_number_of_links" => Ok(GeneratedField::MaxNumberOfLinks), - "probabilitySampler" | "probability_sampler" => Ok(GeneratedField::ProbabilitySampler), - "constantSampler" | "constant_sampler" => Ok(GeneratedField::ConstantSampler), - "rateLimitingSampler" | "rate_limiting_sampler" => Ok(GeneratedField::RateLimitingSampler), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = TraceConfig; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.TraceConfig") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut max_number_of_attributes__ = None; - let mut max_number_of_annotations__ = None; - let mut max_number_of_message_events__ = None; - let mut max_number_of_links__ = None; - let mut sampler__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::MaxNumberOfAttributes => { - if max_number_of_attributes__.is_some() { - return Err(serde::de::Error::duplicate_field("maxNumberOfAttributes")); - } - max_number_of_attributes__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - GeneratedField::MaxNumberOfAnnotations => { - if max_number_of_annotations__.is_some() { - return Err(serde::de::Error::duplicate_field("maxNumberOfAnnotations")); - } - max_number_of_annotations__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - GeneratedField::MaxNumberOfMessageEvents => { - if max_number_of_message_events__.is_some() { - return Err(serde::de::Error::duplicate_field("maxNumberOfMessageEvents")); - } - max_number_of_message_events__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - GeneratedField::MaxNumberOfLinks => { - if max_number_of_links__.is_some() { - return Err(serde::de::Error::duplicate_field("maxNumberOfLinks")); - } - max_number_of_links__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - GeneratedField::ProbabilitySampler => { - if sampler__.is_some() { - return Err(serde::de::Error::duplicate_field("probabilitySampler")); - } - sampler__ = map_.next_value::<::std::option::Option<_>>()?.map(trace_config::Sampler::ProbabilitySampler) -; - } - GeneratedField::ConstantSampler => { - if sampler__.is_some() { - return Err(serde::de::Error::duplicate_field("constantSampler")); - } - sampler__ = map_.next_value::<::std::option::Option<_>>()?.map(trace_config::Sampler::ConstantSampler) -; - } - GeneratedField::RateLimitingSampler => { - if sampler__.is_some() { - return Err(serde::de::Error::duplicate_field("rateLimitingSampler")); - } - sampler__ = map_.next_value::<::std::option::Option<_>>()?.map(trace_config::Sampler::RateLimitingSampler) -; - } - } - } - Ok(TraceConfig { - max_number_of_attributes: max_number_of_attributes__.unwrap_or_default(), - max_number_of_annotations: max_number_of_annotations__.unwrap_or_default(), - max_number_of_message_events: max_number_of_message_events__.unwrap_or_default(), - max_number_of_links: max_number_of_links__.unwrap_or_default(), - sampler: sampler__, - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.TraceConfig", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for TruncatableString { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.value.is_empty() { - len += 1; - } - if self.truncated_byte_count != 0 { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("opencensus.proto.trace.v1.TruncatableString", len)?; - if !self.value.is_empty() { - struct_ser.serialize_field("value", &self.value)?; - } - if self.truncated_byte_count != 0 { - struct_ser.serialize_field("truncated_byte_count", &self.truncated_byte_count)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for TruncatableString { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "value", - "truncated_byte_count", - "truncatedByteCount", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Value, - TruncatedByteCount, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "value" => Ok(GeneratedField::Value), - "truncatedByteCount" | "truncated_byte_count" => Ok(GeneratedField::TruncatedByteCount), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = TruncatableString; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct opencensus.proto.trace.v1.TruncatableString") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut value__ = None; - let mut truncated_byte_count__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Value => { - if value__.is_some() { - return Err(serde::de::Error::duplicate_field("value")); - } - value__ = Some(map_.next_value()?); - } - GeneratedField::TruncatedByteCount => { - if truncated_byte_count__.is_some() { - return Err(serde::de::Error::duplicate_field("truncatedByteCount")); - } - truncated_byte_count__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - } - } - Ok(TruncatableString { - value: value__.unwrap_or_default(), - truncated_byte_count: truncated_byte_count__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("opencensus.proto.trace.v1.TruncatableString", FIELDS, GeneratedVisitor) - } -} diff --git a/src/generated/xds.core.v3.rs b/src/generated/xds.core.v3.rs index 06a40d4..8643b06 100644 --- a/src/generated/xds.core.v3.rs +++ b/src/generated/xds.core.v3.rs @@ -1,4 +1,27 @@ // This file is @generated by prost-build. +/// CidrRange specifies an IP Address and a prefix length to construct +/// the subnet mask for a `CIDR <`_> range. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CidrRange { + /// IPv4 or IPv6 address, e.g. ``192.0.0.0`` or ``2001:db8::``. + #[prost(string, tag = "1")] + pub address_prefix: ::prost::alloc::string::String, + /// Length of prefix, e.g. 0, 32. Defaults to 0 when unset. + #[prost(message, optional, tag = "2")] + pub prefix_len: ::core::option::Option< + super::super::super::google::protobuf::UInt32Value, + >, +} +impl ::prost::Name for CidrRange { + const NAME: &'static str = "CidrRange"; + const PACKAGE: &'static str = "xds.core.v3"; + fn full_name() -> ::prost::alloc::string::String { + "xds.core.v3.CidrRange".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xds.core.v3.CidrRange".into() + } +} /// Message type for extension configuration. #[derive(Clone, PartialEq, ::prost::Message)] pub struct TypedExtensionConfig { diff --git a/src/generated/xds.core.v3.serde.rs b/src/generated/xds.core.v3.serde.rs index 9dcb484..5ed7114 100644 --- a/src/generated/xds.core.v3.serde.rs +++ b/src/generated/xds.core.v3.serde.rs @@ -89,6 +89,116 @@ impl<'de> serde::Deserialize<'de> for Authority { deserializer.deserialize_struct("xds.core.v3.Authority", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for CidrRange { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.address_prefix.is_empty() { + len += 1; + } + if self.prefix_len.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xds.core.v3.CidrRange", len)?; + if !self.address_prefix.is_empty() { + struct_ser.serialize_field("address_prefix", &self.address_prefix)?; + } + if let Some(v) = self.prefix_len.as_ref() { + struct_ser.serialize_field("prefix_len", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for CidrRange { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "address_prefix", + "addressPrefix", + "prefix_len", + "prefixLen", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + AddressPrefix, + PrefixLen, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "addressPrefix" | "address_prefix" => Ok(GeneratedField::AddressPrefix), + "prefixLen" | "prefix_len" => Ok(GeneratedField::PrefixLen), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = CidrRange; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xds.core.v3.CidrRange") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut address_prefix__ = None; + let mut prefix_len__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::AddressPrefix => { + if address_prefix__.is_some() { + return Err(serde::de::Error::duplicate_field("addressPrefix")); + } + address_prefix__ = Some(map_.next_value()?); + } + GeneratedField::PrefixLen => { + if prefix_len__.is_some() { + return Err(serde::de::Error::duplicate_field("prefixLen")); + } + prefix_len__ = map_.next_value()?; + } + } + } + Ok(CidrRange { + address_prefix: address_prefix__.unwrap_or_default(), + prefix_len: prefix_len__, + }) + } + } + deserializer.deserialize_struct("xds.core.v3.CidrRange", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for CollectionEntry { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/src/generated/xds.r#type.matcher.v3.rs b/src/generated/xds.r#type.matcher.v3.rs index e614b0f..6ece753 100644 --- a/src/generated/xds.r#type.matcher.v3.rs +++ b/src/generated/xds.r#type.matcher.v3.rs @@ -162,6 +162,14 @@ pub mod matcher { /// What to do if a match is successful. #[derive(Clone, PartialEq, ::prost::Message)] pub struct OnMatch { + /// If true and the Matcher matches, the action will be taken but the caller + /// will behave as if the Matcher did not match. A subsequent matcher or + /// on_no_match action will be used instead. + /// This field is not supported in all contexts in which the matcher API is + /// used. If this field is set in a context in which it's not supported, + /// the resource will be rejected. + #[prost(bool, tag = "3")] + pub keep_matching: bool, #[prost(oneof = "on_match::OnMatch", tags = "1, 2")] pub on_match: ::core::option::Option, } diff --git a/src/generated/xds.r#type.matcher.v3.serde.rs b/src/generated/xds.r#type.matcher.v3.serde.rs index e150e71..84a0fff 100644 --- a/src/generated/xds.r#type.matcher.v3.serde.rs +++ b/src/generated/xds.r#type.matcher.v3.serde.rs @@ -1019,10 +1019,16 @@ impl serde::Serialize for matcher::OnMatch { { use serde::ser::SerializeStruct; let mut len = 0; + if self.keep_matching { + len += 1; + } if self.on_match.is_some() { len += 1; } let mut struct_ser = serializer.serialize_struct("xds.r#type.matcher.v3.Matcher.OnMatch", len)?; + if self.keep_matching { + struct_ser.serialize_field("keep_matching", &self.keep_matching)?; + } if let Some(v) = self.on_match.as_ref() { match v { matcher::on_match::OnMatch::Matcher(v) => { @@ -1043,12 +1049,15 @@ impl<'de> serde::Deserialize<'de> for matcher::OnMatch { D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ + "keep_matching", + "keepMatching", "matcher", "action", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { + KeepMatching, Matcher, Action, } @@ -1072,6 +1081,7 @@ impl<'de> serde::Deserialize<'de> for matcher::OnMatch { E: serde::de::Error, { match value { + "keepMatching" | "keep_matching" => Ok(GeneratedField::KeepMatching), "matcher" => Ok(GeneratedField::Matcher), "action" => Ok(GeneratedField::Action), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), @@ -1093,9 +1103,16 @@ impl<'de> serde::Deserialize<'de> for matcher::OnMatch { where V: serde::de::MapAccess<'de>, { + let mut keep_matching__ = None; let mut on_match__ = None; while let Some(k) = map_.next_key()? { match k { + GeneratedField::KeepMatching => { + if keep_matching__.is_some() { + return Err(serde::de::Error::duplicate_field("keepMatching")); + } + keep_matching__ = Some(map_.next_value()?); + } GeneratedField::Matcher => { if on_match__.is_some() { return Err(serde::de::Error::duplicate_field("matcher")); @@ -1113,6 +1130,7 @@ impl<'de> serde::Deserialize<'de> for matcher::OnMatch { } } Ok(matcher::OnMatch { + keep_matching: keep_matching__.unwrap_or_default(), on_match: on_match__, }) } diff --git a/src/lib.rs b/src/lib.rs index f264ab2..8a33606 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,17 +1,24 @@ #![allow(clippy::doc_lazy_continuation)] #![doc = include_str!("../README.md")] +#[cfg(not(feature = "generate_only"))] mod any; +#[cfg(not(feature = "generate_only"))] #[allow(clippy::all, clippy::pedantic, clippy::nursery)] mod generated; +#[cfg(feature = "generate_only")] +mod generated {} + pub mod pb { pub use crate::generated::*; } +#[cfg(not(feature = "generate_only"))] pub use any::WellKnownTypes; +#[cfg(not(feature = "generate_only"))] mod value; /// A serialized file descriptor set containing the entirety of the XDS API. diff --git a/src/xds-descriptors.bin b/src/xds-descriptors.bin index 90d8151d9ff7a8488572cc6925b61b774a77cc55..c26f1584630b047855422da1ed7566abe3a5e24a 100644 GIT binary patch delta 241172 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%0A3sUt;CQea7wc;Ax_>&x0pNvd>cwIg)+; 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 z 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�{v*z7hEBs7ojGn*~nD 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: &mut W, depth: usize, line: &str) -> io::Result<( } fn check_protoc_version(sh: &Shell) -> anyhow::Result { - let output = cmd!(sh, "protoc --version").read()?; + let protoc_path = env::var("PROTOC").unwrap_or_else(|_| "protoc".to_string()); + let output = cmd!(sh, "{protoc_path} --version").read()?; let Some(version) = output.split_ascii_whitespace().last() else { anyhow::bail!("oops: couldn't parse protoc version"); }; diff --git a/tests/test_any.rs b/tests/test_any.rs index 827516f..8ac8fe8 100644 --- a/tests/test_any.rs +++ b/tests/test_any.rs @@ -1,4 +1,4 @@ -#[cfg(test)] +#[cfg(all(test, not(feature = "generate_only")))] mod any { use xds_api::pb::{ envoy::{ diff --git a/tests/test_pbjson.rs b/tests/test_pbjson.rs index d6d9b06..cc46f8e 100644 --- a/tests/test_pbjson.rs +++ b/tests/test_pbjson.rs @@ -1,4 +1,4 @@ -#[cfg(all(test, feature = "pbjson"))] +#[cfg(all(test, feature = "pbjson", not(feature = "generate_only")))] mod pbjson { use serde_json::json; diff --git a/tests/test_value.rs b/tests/test_value.rs index 56735f0..06b6f2e 100644 --- a/tests/test_value.rs +++ b/tests/test_value.rs @@ -1,4 +1,4 @@ -#[cfg(test)] +#[cfg(all(test, not(feature = "generate_only")))] mod value { use std::u64;