diff --git a/crates/ruma-common/src/directory.rs b/crates/ruma-common/src/directory.rs index 1708c3b4..5f469dd1 100644 --- a/crates/ruma-common/src/directory.rs +++ b/crates/ruma-common/src/directory.rs @@ -1,18 +1,13 @@ //! Common types for room directory endpoints. -use std::fmt; - use crate::{ serde::{Incoming, StringEnum}, OwnedRoomAliasId, OwnedRoomId, }; use js_int::UInt; -use serde::{ - de::{Error, MapAccess, Visitor}, - ser::SerializeStruct, - Deserialize, Deserializer, Serialize, Serializer, -}; -use serde_json::Value as JsonValue; +use serde::{Deserialize, Serialize}; + +mod room_network_serde; use crate::{OwnedMxcUri, PrivOwnedStr}; @@ -154,84 +149,6 @@ impl<'a> Default for RoomNetwork<'a> { } } -impl<'a> Serialize for RoomNetwork<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut state; - match self { - Self::Matrix => { - state = serializer.serialize_struct("RoomNetwork", 0)?; - } - Self::All => { - state = serializer.serialize_struct("RoomNetwork", 1)?; - state.serialize_field("include_all_networks", &true)?; - } - Self::ThirdParty(network) => { - state = serializer.serialize_struct("RoomNetwork", 1)?; - state.serialize_field("third_party_instance_id", network)?; - } - } - state.end() - } -} - -impl<'de> Deserialize<'de> for IncomingRoomNetwork { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_map(RoomNetworkVisitor) - } -} - -struct RoomNetworkVisitor; -impl<'de> Visitor<'de> for RoomNetworkVisitor { - type Value = IncomingRoomNetwork; - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("Network selection") - } - - fn visit_map(self, mut access: M) -> Result - where - M: MapAccess<'de>, - { - let mut include_all_networks = false; - let mut third_party_instance_id = None; - while let Some((key, value)) = access.next_entry::()? { - match key.as_str() { - "include_all_networks" => { - include_all_networks = match value.as_bool() { - Some(b) => b, - _ => false, - } - } - "third_party_instance_id" => { - third_party_instance_id = value.as_str().map(|v| v.to_owned()); - } - _ => {} - }; - } - - if include_all_networks { - if third_party_instance_id.is_none() { - Ok(IncomingRoomNetwork::All) - } else { - Err(M::Error::custom( - "`include_all_networks = true` and `third_party_instance_id` are mutually exclusive.", - )) - } - } else { - Ok(match third_party_instance_id { - Some(network) => IncomingRoomNetwork::ThirdParty(network), - None => IncomingRoomNetwork::Matrix, - }) - } - } -} - /// The rule used for users wishing to join a public room. #[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))] #[derive(Clone, Debug, PartialEq, Eq, StringEnum)] diff --git a/crates/ruma-common/src/directory/room_network_serde.rs b/crates/ruma-common/src/directory/room_network_serde.rs new file mode 100644 index 00000000..a1b2e643 --- /dev/null +++ b/crates/ruma-common/src/directory/room_network_serde.rs @@ -0,0 +1,88 @@ +use std::fmt; + +use serde::{ + de::{Error, MapAccess, Visitor}, + ser::SerializeStruct, + Deserialize, Deserializer, Serialize, Serializer, +}; +use serde_json::Value as JsonValue; + +use super::{IncomingRoomNetwork, RoomNetwork}; + +impl<'a> Serialize for RoomNetwork<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut state; + match self { + Self::Matrix => { + state = serializer.serialize_struct("RoomNetwork", 0)?; + } + Self::All => { + state = serializer.serialize_struct("RoomNetwork", 1)?; + state.serialize_field("include_all_networks", &true)?; + } + Self::ThirdParty(network) => { + state = serializer.serialize_struct("RoomNetwork", 1)?; + state.serialize_field("third_party_instance_id", network)?; + } + } + state.end() + } +} + +impl<'de> Deserialize<'de> for IncomingRoomNetwork { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_map(RoomNetworkVisitor) + } +} + +struct RoomNetworkVisitor; +impl<'de> Visitor<'de> for RoomNetworkVisitor { + type Value = IncomingRoomNetwork; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("Network selection") + } + + fn visit_map(self, mut access: M) -> Result + where + M: MapAccess<'de>, + { + let mut include_all_networks = false; + let mut third_party_instance_id = None; + while let Some((key, value)) = access.next_entry::()? { + match key.as_str() { + "include_all_networks" => { + include_all_networks = match value.as_bool() { + Some(b) => b, + _ => false, + } + } + "third_party_instance_id" => { + third_party_instance_id = value.as_str().map(|v| v.to_owned()); + } + _ => {} + }; + } + + if include_all_networks { + if third_party_instance_id.is_none() { + Ok(IncomingRoomNetwork::All) + } else { + Err(M::Error::custom( + "`include_all_networks = true` and `third_party_instance_id` are mutually exclusive.", + )) + } + } else { + Ok(match third_party_instance_id { + Some(network) => IncomingRoomNetwork::ThirdParty(network), + None => IncomingRoomNetwork::Matrix, + }) + } + } +}