common: Move RoomNetwork serde in its own file

This commit is contained in:
Kévin Commaille 2022-08-01 19:58:52 +02:00 committed by Kévin Commaille
parent 4db337b86a
commit 226502b9bc
2 changed files with 91 additions and 86 deletions

View File

@ -1,18 +1,13 @@
//! Common types for room directory endpoints. //! Common types for room directory endpoints.
use std::fmt;
use crate::{ use crate::{
serde::{Incoming, StringEnum}, serde::{Incoming, StringEnum},
OwnedRoomAliasId, OwnedRoomId, OwnedRoomAliasId, OwnedRoomId,
}; };
use js_int::UInt; use js_int::UInt;
use serde::{ use serde::{Deserialize, Serialize};
de::{Error, MapAccess, Visitor},
ser::SerializeStruct, mod room_network_serde;
Deserialize, Deserializer, Serialize, Serializer,
};
use serde_json::Value as JsonValue;
use crate::{OwnedMxcUri, PrivOwnedStr}; use crate::{OwnedMxcUri, PrivOwnedStr};
@ -154,84 +149,6 @@ impl<'a> Default for RoomNetwork<'a> {
} }
} }
impl<'a> Serialize for RoomNetwork<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<D>(deserializer: D) -> Result<Self, D::Error>
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<M>(self, mut access: M) -> Result<Self::Value, M::Error>
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::<String, JsonValue>()? {
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. /// The rule used for users wishing to join a public room.
#[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))] #[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))]
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)] #[derive(Clone, Debug, PartialEq, Eq, StringEnum)]

View File

@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<D>(deserializer: D) -> Result<Self, D::Error>
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<M>(self, mut access: M) -> Result<Self::Value, M::Error>
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::<String, JsonValue>()? {
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,
})
}
}
}