diff --git a/crates/xmtp_proto/proto_version b/crates/xmtp_proto/proto_version index aba460fee9..2a9c9a3a9b 100644 --- a/crates/xmtp_proto/proto_version +++ b/crates/xmtp_proto/proto_version @@ -1 +1 @@ -e6f640a8994dad1779da0280b15be482c0bb4bb8 +ac2aa57f7482e354b1903f562203169eb1cc479f diff --git a/crates/xmtp_proto/src/gen/proto_descriptor.bin b/crates/xmtp_proto/src/gen/proto_descriptor.bin index b2d195784b..7fa0feea0e 100644 Binary files a/crates/xmtp_proto/src/gen/proto_descriptor.bin and b/crates/xmtp_proto/src/gen/proto_descriptor.bin differ diff --git a/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.rs b/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.rs index 8205bd5643..84d1d01754 100644 --- a/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.rs +++ b/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.rs @@ -762,6 +762,345 @@ impl ::prost::Name for SubscribeWelcomeMessagesRequest { "/xmtp.mls.api.v1.SubscribeWelcomeMessagesRequest".into() } } +/// Client -> server. Sent one or more times over the life of the stream. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SubscribeRequest { + #[prost(oneof = "subscribe_request::Version", tags = "1")] + pub version: ::core::option::Option, +} +/// Nested message and enum types in `SubscribeRequest`. +pub mod subscribe_request { + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct V1 { + /// Each frame is exactly one of: a mutation, a Ping, or a Pong. + #[prost(oneof = "v1::Request", tags = "1, 2, 3")] + pub request: ::core::option::Option, + } + /// Nested message and enum types in `V1`. + pub mod v1 { + /// Add and/or remove subscriptions in place (applied atomically per frame). + /// Topics use the kind-prefixed binary representation shared with the + /// decentralized backend (XIP-49 §3.3.2): the first byte is the topic kind, + /// the remainder is the identifier. This RPC initially serves + /// TOPIC_KIND_GROUP_MESSAGES_V1 (0x00, identifier = group_id) and + /// TOPIC_KIND_WELCOME_MESSAGES_V1 (0x01, identifier = installation_key); + /// a topic whose kind the node does not serve fails the stream with + /// INVALID_ARGUMENT. Future kinds (key packages, identity updates) are + /// adopted via the capabilities advertised on Started. + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct Mutate { + /// begin delivering these topics + #[prost(message, repeated, tag = "1")] + pub adds: ::prost::alloc::vec::Vec, + /// topics to stop delivering + #[prost(bytes = "vec", repeated, tag = "2")] + pub removes: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, + /// Catch this Mutate's adds up to the live edge — history, TopicsLive + /// markers, and the wave's CatchupComplete — but do NOT register them + /// for live delivery. The markers then mean "you have everything as of + /// now". Combined with half-closing the request stream, this is the + /// bounded catch-up ("sync") mode: the server finishes the wave and then + /// closes the stream itself. Removals in the Mutate are unaffected. + #[prost(bool, tag = "3")] + pub history_only: bool, + /// Client-chosen correlation id, echoed on this wave's CatchupComplete + /// so completions are attributable when waves overlap. SHOULD be unique + /// per stream; 0 = no correlation requested (still echoed as 0). + #[prost(uint64, tag = "4")] + pub mutate_id: u64, + } + /// Nested message and enum types in `Mutate`. + pub mod mutate { + /// A topic to subscribe, with the cursor to resume from. + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] + pub struct Subscription { + #[prost(bytes = "vec", tag = "1")] + pub topic: ::prost::alloc::vec::Vec, + /// Deliver ids greater than this; 0 = from the beginning. For a newly + /// joined group, a client SHOULD seed this from the welcome's encrypted + /// WelcomeMetadata.message_cursor so a new membership does not refetch + /// pre-join history it cannot decrypt; for a new installation's welcome + /// topic, 0 is how pending welcomes are collected. + #[prost(uint64, tag = "2")] + pub id_cursor: u64, + } + impl ::prost::Name for Subscription { + const NAME: &'static str = "Subscription"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeRequest.V1.Mutate.Subscription".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeRequest.V1.Mutate.Subscription".into() + } + } + } + impl ::prost::Name for Mutate { + const NAME: &'static str = "Mutate"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeRequest.V1.Mutate".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeRequest.V1.Mutate".into() + } + } + /// Each frame is exactly one of: a mutation, a Ping, or a Pong. + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Request { + #[prost(message, tag = "1")] + Mutate(Mutate), + /// liveness challenge (e.g. probe the link after resuming) + #[prost(message, tag = "2")] + Ping(super::super::Ping), + /// answer to a server Ping + #[prost(message, tag = "3")] + Pong(super::super::Pong), + } + } + impl ::prost::Name for V1 { + const NAME: &'static str = "V1"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeRequest.V1".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeRequest.V1".into() + } + } + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Version { + #[prost(message, tag = "1")] + V1(V1), + } +} +impl ::prost::Name for SubscribeRequest { + const NAME: &'static str = "SubscribeRequest"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeRequest".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeRequest".into() + } +} +/// Server -> client. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SubscribeResponse { + #[prost(oneof = "subscribe_response::Version", tags = "1")] + pub version: ::core::option::Option, +} +/// Nested message and enum types in `SubscribeResponse`. +pub mod subscribe_response { + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct V1 { + #[prost(oneof = "v1::Response", tags = "1, 2, 3, 4, 5, 6")] + pub response: ::core::option::Option, + } + /// Nested message and enum types in `V1`. + pub mod v1 { + /// A batch of new messages; group and welcome messages share the stream, + /// depending on which subscriptions are active. + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct Messages { + #[prost(message, repeated, tag = "1")] + pub group_messages: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "2")] + pub welcome_messages: ::prost::alloc::vec::Vec, + } + impl ::prost::Name for Messages { + const NAME: &'static str = "Messages"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeResponse.V1.Messages".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeResponse.V1.Messages".into() + } + } + /// The first frame on every stream. + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] + pub struct Started { + /// The server's ping cadence (ms): the basis for the client's staleness + /// threshold and the server's reap deadline. + #[prost(uint32, tag = "1")] + pub keepalive_interval_ms: u32, + /// Optional protocol features the node supports on this stream. The node + /// silently ignores request types it does not understand, so a client + /// MUST NOT send an optional request type whose capability the node did + /// not advertise (it would hang waiting on a response that never comes). + #[prost(enumeration = "Capability", repeated, tag = "2")] + pub capabilities: ::prost::alloc::vec::Vec, + } + impl ::prost::Name for Started { + const NAME: &'static str = "Started"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeResponse.V1.Started".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeResponse.V1.Started".into() + } + } + /// Sent once per Mutate that adds subscriptions (a catch-up "wave"), after + /// the wave's last TopicsLive: everything the Mutate asked for is delivered. + #[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] + pub struct CatchupComplete { + /// echoes the Mutate that started this wave (0 if none given) + #[prost(uint64, tag = "1")] + pub mutate_id: u64, + } + impl ::prost::Name for CatchupComplete { + const NAME: &'static str = "CatchupComplete"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeResponse.V1.CatchupComplete".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeResponse.V1.CatchupComplete".into() + } + } + /// Emitted when topics finish catch-up, AFTER the last history frame for + /// them — including any live messages that queued up behind the catch-up, + /// which were equally historical from the client's perspective — so every + /// later frame for a listed topic is live tail. Informational only: delivery + /// correctness (no duplicates, no gaps) never depends on it. Re-adding a + /// topic re-runs catch-up and re-emits it; receivers treat it idempotently. + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] + pub struct TopicsLive { + /// kind-prefixed topics now tailing live + #[prost(bytes = "vec", repeated, tag = "1")] + pub topics: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, + } + impl ::prost::Name for TopicsLive { + const NAME: &'static str = "TopicsLive"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeResponse.V1.TopicsLive".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeResponse.V1.TopicsLive".into() + } + } + /// Optional per-stream protocol features (none defined yet; future + /// revisions add values, e.g. fetch-over-stream lookups answered with the + /// same read view that feeds the stream, or new streamable topic kinds). + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum Capability { + Unspecified = 0, + } + impl Capability { + /// 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 => "CAPABILITY_UNSPECIFIED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "CAPABILITY_UNSPECIFIED" => Some(Self::Unspecified), + _ => None, + } + } + } + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Response { + #[prost(message, tag = "1")] + Messages(Messages), + /// sent once, immediately on open, before any catch-up + #[prost(message, tag = "2")] + Started(Started), + /// idle liveness challenge; receiver MUST answer with Pong + #[prost(message, tag = "3")] + Ping(super::super::Ping), + /// answer to a client Ping + #[prost(message, tag = "4")] + Pong(super::super::Pong), + /// these topics just crossed from catch-up to live + #[prost(message, tag = "5")] + TopicsLive(TopicsLive), + /// a Mutate's adds are fully delivered + #[prost(message, tag = "6")] + CatchupComplete(CatchupComplete), + } + } + impl ::prost::Name for V1 { + const NAME: &'static str = "V1"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeResponse.V1".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeResponse.V1".into() + } + } + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Version { + #[prost(message, tag = "1")] + V1(V1), + } +} +impl ::prost::Name for SubscribeResponse { + const NAME: &'static str = "SubscribeResponse"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeResponse".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeResponse".into() + } +} +/// Liveness challenge/response, shared across versions. Either peer MAY send a +/// Ping; the receiver MUST reply with a Pong echoing the nonce. The sender closes +/// the stream if no Pong arrives within its deadline — how a node reaps a vanished +/// peer (e.g. a mobile client the OS suspended behind a proxy that still ACKs the +/// transport). +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Ping { + #[prost(uint64, tag = "1")] + pub nonce: u64, +} +impl ::prost::Name for Ping { + const NAME: &'static str = "Ping"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.Ping".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.Ping".into() + } +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Pong { + /// echoes the nonce of the Ping it answers + #[prost(uint64, tag = "1")] + pub nonce: u64, +} +impl ::prost::Name for Pong { + const NAME: &'static str = "Pong"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.Pong".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.Pong".into() + } +} #[derive(Clone, PartialEq, ::prost::Message)] pub struct BatchPublishCommitLogRequest { #[prost(message, repeated, tag = "1")] @@ -1057,6 +1396,20 @@ pub mod mls_api_server { tonic::Response, tonic::Status, >; + /// Server streaming response type for the Subscribe method. + type SubscribeStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result, + > + + std::marker::Send + + 'static; + /// Bidirectional subscription (XIP-83). One long-lived stream the client mutates + /// in place via add/remove topic deltas, with WebSocket-style liveness ping/pong. + /// A single stream MAY carry both group-message and welcome topics. + /// gRPC-only: bidirectional streaming has no HTTP/grpc-gateway mapping. + async fn subscribe( + &self, + request: tonic::Request>, + ) -> std::result::Result, tonic::Status>; async fn batch_publish_commit_log( &self, request: tonic::Request, @@ -1656,6 +2009,54 @@ pub mod mls_api_server { }; Box::pin(fut) } + "/xmtp.mls.api.v1.MlsApi/Subscribe" => { + #[allow(non_camel_case_types)] + struct SubscribeSvc(pub Arc); + impl< + T: MlsApi, + > tonic::server::StreamingService + for SubscribeSvc { + type Response = super::SubscribeResponse; + type ResponseStream = T::SubscribeStream; + 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 { + ::subscribe(&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 = SubscribeSvc(inner); + let codec = tonic_prost::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) + } "/xmtp.mls.api.v1.MlsApi/BatchPublishCommitLog" => { #[allow(non_camel_case_types)] struct BatchPublishCommitLogSvc(pub Arc); diff --git a/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.serde.rs b/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.serde.rs index 86ca7f1ab0..6526357791 100644 --- a/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.serde.rs +++ b/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.serde.rs @@ -2352,6 +2352,204 @@ impl<'de> serde::Deserialize<'de> for PagingInfo { deserializer.deserialize_struct("xmtp.mls.api.v1.PagingInfo", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for Ping { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.nonce != 0 { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.Ping", len)?; + if self.nonce != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("nonce", ToString::to_string(&self.nonce).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for Ping { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "nonce", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Nonce, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> 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 { + "nonce" => Ok(GeneratedField::Nonce), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = Ping; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.Ping") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut nonce__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Nonce => { + if nonce__.is_some() { + return Err(serde::de::Error::duplicate_field("nonce")); + } + nonce__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(Ping { + nonce: nonce__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.Ping", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for Pong { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.nonce != 0 { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.Pong", len)?; + if self.nonce != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("nonce", ToString::to_string(&self.nonce).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for Pong { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "nonce", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Nonce, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> 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 { + "nonce" => Ok(GeneratedField::Nonce), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = Pong; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.Pong") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut nonce__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Nonce => { + if nonce__.is_some() { + return Err(serde::de::Error::duplicate_field("nonce")); + } + nonce__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(Pong { + nonce: nonce__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.Pong", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for PublishCommitLogRequest { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -4020,6 +4218,1274 @@ impl<'de> serde::Deserialize<'de> for subscribe_group_messages_request::Filter { deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeGroupMessagesRequest.Filter", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for SubscribeRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.version.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeRequest", len)?; + if let Some(v) = self.version.as_ref() { + match v { + subscribe_request::Version::V1(v) => { + struct_ser.serialize_field("v1", v)?; + } + } + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for SubscribeRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "v1", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + V1, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> 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 { + "v1" => Ok(GeneratedField::V1), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = SubscribeRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut version__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::V1 => { + if version__.is_some() { + return Err(serde::de::Error::duplicate_field("v1")); + } + version__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_request::Version::V1) +; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(SubscribeRequest { + version: version__, + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_request::V1 { + #[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.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeRequest.V1", len)?; + if let Some(v) = self.request.as_ref() { + match v { + subscribe_request::v1::Request::Mutate(v) => { + struct_ser.serialize_field("mutate", v)?; + } + subscribe_request::v1::Request::Ping(v) => { + struct_ser.serialize_field("ping", v)?; + } + subscribe_request::v1::Request::Pong(v) => { + struct_ser.serialize_field("pong", v)?; + } + } + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_request::V1 { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "mutate", + "ping", + "pong", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Mutate, + Ping, + Pong, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> 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 { + "mutate" => Ok(GeneratedField::Mutate), + "ping" => Ok(GeneratedField::Ping), + "pong" => Ok(GeneratedField::Pong), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_request::V1; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeRequest.V1") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut request__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Mutate => { + if request__.is_some() { + return Err(serde::de::Error::duplicate_field("mutate")); + } + request__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_request::v1::Request::Mutate) +; + } + GeneratedField::Ping => { + if request__.is_some() { + return Err(serde::de::Error::duplicate_field("ping")); + } + request__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_request::v1::Request::Ping) +; + } + GeneratedField::Pong => { + if request__.is_some() { + return Err(serde::de::Error::duplicate_field("pong")); + } + request__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_request::v1::Request::Pong) +; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_request::V1 { + request: request__, + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeRequest.V1", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_request::v1::Mutate { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.adds.is_empty() { + len += 1; + } + if !self.removes.is_empty() { + len += 1; + } + if self.history_only { + len += 1; + } + if self.mutate_id != 0 { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeRequest.V1.Mutate", len)?; + if !self.adds.is_empty() { + struct_ser.serialize_field("adds", &self.adds)?; + } + if !self.removes.is_empty() { + struct_ser.serialize_field("removes", &self.removes.iter().map(pbjson::private::base64::encode).collect::>())?; + } + if self.history_only { + struct_ser.serialize_field("history_only", &self.history_only)?; + } + if self.mutate_id != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("mutate_id", ToString::to_string(&self.mutate_id).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_request::v1::Mutate { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "adds", + "removes", + "history_only", + "historyOnly", + "mutate_id", + "mutateId", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Adds, + Removes, + HistoryOnly, + MutateId, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> 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 { + "adds" => Ok(GeneratedField::Adds), + "removes" => Ok(GeneratedField::Removes), + "historyOnly" | "history_only" => Ok(GeneratedField::HistoryOnly), + "mutateId" | "mutate_id" => Ok(GeneratedField::MutateId), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_request::v1::Mutate; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeRequest.V1.Mutate") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut adds__ = None; + let mut removes__ = None; + let mut history_only__ = None; + let mut mutate_id__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Adds => { + if adds__.is_some() { + return Err(serde::de::Error::duplicate_field("adds")); + } + adds__ = Some(map_.next_value()?); + } + GeneratedField::Removes => { + if removes__.is_some() { + return Err(serde::de::Error::duplicate_field("removes")); + } + removes__ = + Some(map_.next_value::>>()? + .into_iter().map(|x| x.0).collect()) + ; + } + GeneratedField::HistoryOnly => { + if history_only__.is_some() { + return Err(serde::de::Error::duplicate_field("historyOnly")); + } + history_only__ = Some(map_.next_value()?); + } + GeneratedField::MutateId => { + if mutate_id__.is_some() { + return Err(serde::de::Error::duplicate_field("mutateId")); + } + mutate_id__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_request::v1::Mutate { + adds: adds__.unwrap_or_default(), + removes: removes__.unwrap_or_default(), + history_only: history_only__.unwrap_or_default(), + mutate_id: mutate_id__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeRequest.V1.Mutate", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_request::v1::mutate::Subscription { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.topic.is_empty() { + len += 1; + } + if self.id_cursor != 0 { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeRequest.V1.Mutate.Subscription", len)?; + if !self.topic.is_empty() { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("topic", pbjson::private::base64::encode(&self.topic).as_str())?; + } + if self.id_cursor != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("id_cursor", ToString::to_string(&self.id_cursor).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_request::v1::mutate::Subscription { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "topic", + "id_cursor", + "idCursor", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Topic, + IdCursor, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> 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 { + "topic" => Ok(GeneratedField::Topic), + "idCursor" | "id_cursor" => Ok(GeneratedField::IdCursor), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_request::v1::mutate::Subscription; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeRequest.V1.Mutate.Subscription") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut topic__ = None; + let mut id_cursor__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Topic => { + if topic__.is_some() { + return Err(serde::de::Error::duplicate_field("topic")); + } + topic__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + GeneratedField::IdCursor => { + if id_cursor__.is_some() { + return Err(serde::de::Error::duplicate_field("idCursor")); + } + id_cursor__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_request::v1::mutate::Subscription { + topic: topic__.unwrap_or_default(), + id_cursor: id_cursor__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeRequest.V1.Mutate.Subscription", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for SubscribeResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.version.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeResponse", len)?; + if let Some(v) = self.version.as_ref() { + match v { + subscribe_response::Version::V1(v) => { + struct_ser.serialize_field("v1", v)?; + } + } + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for SubscribeResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "v1", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + V1, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> 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 { + "v1" => Ok(GeneratedField::V1), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = SubscribeResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut version__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::V1 => { + if version__.is_some() { + return Err(serde::de::Error::duplicate_field("v1")); + } + version__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_response::Version::V1) +; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(SubscribeResponse { + version: version__, + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeResponse", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_response::V1 { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.response.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1", len)?; + if let Some(v) = self.response.as_ref() { + match v { + subscribe_response::v1::Response::Messages(v) => { + struct_ser.serialize_field("messages", v)?; + } + subscribe_response::v1::Response::Started(v) => { + struct_ser.serialize_field("started", v)?; + } + subscribe_response::v1::Response::Ping(v) => { + struct_ser.serialize_field("ping", v)?; + } + subscribe_response::v1::Response::Pong(v) => { + struct_ser.serialize_field("pong", v)?; + } + subscribe_response::v1::Response::TopicsLive(v) => { + struct_ser.serialize_field("topics_live", v)?; + } + subscribe_response::v1::Response::CatchupComplete(v) => { + struct_ser.serialize_field("catchup_complete", v)?; + } + } + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_response::V1 { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "messages", + "started", + "ping", + "pong", + "topics_live", + "topicsLive", + "catchup_complete", + "catchupComplete", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Messages, + Started, + Ping, + Pong, + TopicsLive, + CatchupComplete, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> 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 { + "messages" => Ok(GeneratedField::Messages), + "started" => Ok(GeneratedField::Started), + "ping" => Ok(GeneratedField::Ping), + "pong" => Ok(GeneratedField::Pong), + "topicsLive" | "topics_live" => Ok(GeneratedField::TopicsLive), + "catchupComplete" | "catchup_complete" => Ok(GeneratedField::CatchupComplete), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_response::V1; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeResponse.V1") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut response__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Messages => { + if response__.is_some() { + return Err(serde::de::Error::duplicate_field("messages")); + } + response__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_response::v1::Response::Messages) +; + } + GeneratedField::Started => { + if response__.is_some() { + return Err(serde::de::Error::duplicate_field("started")); + } + response__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_response::v1::Response::Started) +; + } + GeneratedField::Ping => { + if response__.is_some() { + return Err(serde::de::Error::duplicate_field("ping")); + } + response__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_response::v1::Response::Ping) +; + } + GeneratedField::Pong => { + if response__.is_some() { + return Err(serde::de::Error::duplicate_field("pong")); + } + response__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_response::v1::Response::Pong) +; + } + GeneratedField::TopicsLive => { + if response__.is_some() { + return Err(serde::de::Error::duplicate_field("topicsLive")); + } + response__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_response::v1::Response::TopicsLive) +; + } + GeneratedField::CatchupComplete => { + if response__.is_some() { + return Err(serde::de::Error::duplicate_field("catchupComplete")); + } + response__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_response::v1::Response::CatchupComplete) +; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_response::V1 { + response: response__, + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_response::v1::Capability { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + let variant = match self { + Self::Unspecified => "CAPABILITY_UNSPECIFIED", + }; + serializer.serialize_str(variant) + } +} +impl<'de> serde::Deserialize<'de> for subscribe_response::v1::Capability { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "CAPABILITY_UNSPECIFIED", + ]; + + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> for GeneratedVisitor { + type Value = subscribe_response::v1::Capability; + + 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 { + "CAPABILITY_UNSPECIFIED" => Ok(subscribe_response::v1::Capability::Unspecified), + _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), + } + } + } + deserializer.deserialize_any(GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_response::v1::CatchupComplete { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.mutate_id != 0 { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.CatchupComplete", len)?; + if self.mutate_id != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("mutate_id", ToString::to_string(&self.mutate_id).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_response::v1::CatchupComplete { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "mutate_id", + "mutateId", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + MutateId, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> 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 { + "mutateId" | "mutate_id" => Ok(GeneratedField::MutateId), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_response::v1::CatchupComplete; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeResponse.V1.CatchupComplete") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut mutate_id__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::MutateId => { + if mutate_id__.is_some() { + return Err(serde::de::Error::duplicate_field("mutateId")); + } + mutate_id__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_response::v1::CatchupComplete { + mutate_id: mutate_id__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.CatchupComplete", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_response::v1::Messages { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.group_messages.is_empty() { + len += 1; + } + if !self.welcome_messages.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.Messages", len)?; + if !self.group_messages.is_empty() { + struct_ser.serialize_field("group_messages", &self.group_messages)?; + } + if !self.welcome_messages.is_empty() { + struct_ser.serialize_field("welcome_messages", &self.welcome_messages)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_response::v1::Messages { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "group_messages", + "groupMessages", + "welcome_messages", + "welcomeMessages", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + GroupMessages, + WelcomeMessages, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> 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 { + "groupMessages" | "group_messages" => Ok(GeneratedField::GroupMessages), + "welcomeMessages" | "welcome_messages" => Ok(GeneratedField::WelcomeMessages), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_response::v1::Messages; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeResponse.V1.Messages") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut group_messages__ = None; + let mut welcome_messages__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::GroupMessages => { + if group_messages__.is_some() { + return Err(serde::de::Error::duplicate_field("groupMessages")); + } + group_messages__ = Some(map_.next_value()?); + } + GeneratedField::WelcomeMessages => { + if welcome_messages__.is_some() { + return Err(serde::de::Error::duplicate_field("welcomeMessages")); + } + welcome_messages__ = Some(map_.next_value()?); + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_response::v1::Messages { + group_messages: group_messages__.unwrap_or_default(), + welcome_messages: welcome_messages__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.Messages", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_response::v1::Started { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.keepalive_interval_ms != 0 { + len += 1; + } + if !self.capabilities.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.Started", len)?; + if self.keepalive_interval_ms != 0 { + struct_ser.serialize_field("keepalive_interval_ms", &self.keepalive_interval_ms)?; + } + if !self.capabilities.is_empty() { + let v = self.capabilities.iter().cloned().map(|v| { + subscribe_response::v1::Capability::try_from(v) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", v))) + }).collect::, _>>()?; + struct_ser.serialize_field("capabilities", &v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_response::v1::Started { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "keepalive_interval_ms", + "keepaliveIntervalMs", + "capabilities", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + KeepaliveIntervalMs, + Capabilities, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> 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 { + "keepaliveIntervalMs" | "keepalive_interval_ms" => Ok(GeneratedField::KeepaliveIntervalMs), + "capabilities" => Ok(GeneratedField::Capabilities), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_response::v1::Started; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeResponse.V1.Started") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut keepalive_interval_ms__ = None; + let mut capabilities__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::KeepaliveIntervalMs => { + if keepalive_interval_ms__.is_some() { + return Err(serde::de::Error::duplicate_field("keepaliveIntervalMs")); + } + keepalive_interval_ms__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::Capabilities => { + if capabilities__.is_some() { + return Err(serde::de::Error::duplicate_field("capabilities")); + } + capabilities__ = Some(map_.next_value::>()?.into_iter().map(|x| x as i32).collect()); + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_response::v1::Started { + keepalive_interval_ms: keepalive_interval_ms__.unwrap_or_default(), + capabilities: capabilities__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.Started", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_response::v1::TopicsLive { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.topics.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.TopicsLive", len)?; + if !self.topics.is_empty() { + struct_ser.serialize_field("topics", &self.topics.iter().map(pbjson::private::base64::encode).collect::>())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_response::v1::TopicsLive { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "topics", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Topics, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> 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 { + "topics" => Ok(GeneratedField::Topics), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_response::v1::TopicsLive; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeResponse.V1.TopicsLive") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut topics__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Topics => { + if topics__.is_some() { + return Err(serde::de::Error::duplicate_field("topics")); + } + topics__ = + Some(map_.next_value::>>()? + .into_iter().map(|x| x.0).collect()) + ; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_response::v1::TopicsLive { + topics: topics__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.TopicsLive", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for SubscribeWelcomeMessagesRequest { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result