events: Move ignored_users serde code into ignored_user_list module
… and optimize it.
This commit is contained in:
parent
289821aa07
commit
ac707e30f0
@ -4,6 +4,7 @@ Breaking changes:
|
|||||||
|
|
||||||
* Remove deprecated `EventType` enum
|
* Remove deprecated `EventType` enum
|
||||||
* Remove deprecated constructors for `RoomMessageEventContent`
|
* Remove deprecated constructors for `RoomMessageEventContent`
|
||||||
|
* Remove `serde::vec_as_map_of_empty` from the public API
|
||||||
|
|
||||||
# 0.10.3
|
# 0.10.3
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ use crate::OwnedUserId;
|
|||||||
#[ruma_event(type = "m.ignored_user_list", kind = GlobalAccountData)]
|
#[ruma_event(type = "m.ignored_user_list", kind = GlobalAccountData)]
|
||||||
pub struct IgnoredUserListEventContent {
|
pub struct IgnoredUserListEventContent {
|
||||||
/// A list of users to ignore.
|
/// A list of users to ignore.
|
||||||
#[serde(with = "crate::serde::vec_as_map_of_empty")]
|
#[serde(with = "vec_as_map_of_empty")]
|
||||||
pub ignored_users: Vec<OwnedUserId>,
|
pub ignored_users: Vec<OwnedUserId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,6 +26,91 @@ impl IgnoredUserListEventContent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod vec_as_map_of_empty {
|
||||||
|
use std::{fmt, marker::PhantomData};
|
||||||
|
|
||||||
|
use serde::{
|
||||||
|
de::{self, Deserialize, Deserializer},
|
||||||
|
ser::{SerializeMap, Serializer},
|
||||||
|
Serialize,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Serialize the given `Vec<T>` as a map of `T => Empty`.
|
||||||
|
#[allow(clippy::ptr_arg)]
|
||||||
|
pub fn serialize<S, T>(vec: &Vec<T>, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
T: Serialize + Eq + Ord,
|
||||||
|
{
|
||||||
|
let mut map = serializer.serialize_map(Some(vec.len()))?;
|
||||||
|
for item in vec {
|
||||||
|
map.serialize_entry(item, &Empty {})?;
|
||||||
|
}
|
||||||
|
map.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialize an object and return the keys as a `Vec<T>`.
|
||||||
|
pub fn deserialize<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
T: Deserialize<'de> + Eq + Ord,
|
||||||
|
{
|
||||||
|
struct MapOfEmptyVisitor<T>(PhantomData<T>);
|
||||||
|
impl<'de, T> de::Visitor<'de> for MapOfEmptyVisitor<T>
|
||||||
|
where
|
||||||
|
T: Deserialize<'de>,
|
||||||
|
{
|
||||||
|
type Value = Vec<T>;
|
||||||
|
|
||||||
|
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "an object/map")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: de::MapAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut items = Vec::with_capacity(map.size_hint().unwrap_or(0));
|
||||||
|
while let Some((item, _)) = map.next_entry::<T, Empty>()? {
|
||||||
|
items.push(item);
|
||||||
|
}
|
||||||
|
Ok(items)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_map(MapOfEmptyVisitor(PhantomData))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize)]
|
||||||
|
struct Empty {}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Empty {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct EmptyMapVisitor;
|
||||||
|
|
||||||
|
impl<'de> de::Visitor<'de> for EmptyMapVisitor {
|
||||||
|
type Value = Empty;
|
||||||
|
|
||||||
|
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "an object/map")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<A>(self, _map: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: de::MapAccess<'de>,
|
||||||
|
{
|
||||||
|
Ok(Empty {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_map(EmptyMapVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use assert_matches::assert_matches;
|
use assert_matches::assert_matches;
|
||||||
|
@ -13,7 +13,6 @@ mod buf;
|
|||||||
pub mod can_be_empty;
|
pub mod can_be_empty;
|
||||||
mod cow;
|
mod cow;
|
||||||
pub mod duration;
|
pub mod duration;
|
||||||
mod empty;
|
|
||||||
pub mod json_string;
|
pub mod json_string;
|
||||||
mod raw;
|
mod raw;
|
||||||
pub mod single_element_seq;
|
pub mod single_element_seq;
|
||||||
@ -26,7 +25,6 @@ pub use self::{
|
|||||||
buf::{json_to_buf, slice_to_buf},
|
buf::{json_to_buf, slice_to_buf},
|
||||||
can_be_empty::{is_empty, CanBeEmpty},
|
can_be_empty::{is_empty, CanBeEmpty},
|
||||||
cow::deserialize_cow_str,
|
cow::deserialize_cow_str,
|
||||||
empty::vec_as_map_of_empty,
|
|
||||||
raw::Raw,
|
raw::Raw,
|
||||||
strings::{
|
strings::{
|
||||||
btreemap_deserialize_v1_powerlevel_values, deserialize_v1_powerlevel, empty_string_as_none,
|
btreemap_deserialize_v1_powerlevel_values, deserialize_v1_powerlevel, empty_string_as_none,
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
use std::fmt;
|
|
||||||
|
|
||||||
use serde::{
|
|
||||||
de::{self, Deserialize},
|
|
||||||
Serialize,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize)]
|
|
||||||
pub struct Empty {}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for Empty {
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: de::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
struct EmptyMapVisitor;
|
|
||||||
|
|
||||||
impl<'de> de::Visitor<'de> for EmptyMapVisitor {
|
|
||||||
type Value = Empty;
|
|
||||||
|
|
||||||
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "an object/map")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_map<A>(self, _map: A) -> Result<Self::Value, A::Error>
|
|
||||||
where
|
|
||||||
A: de::MapAccess<'de>,
|
|
||||||
{
|
|
||||||
Ok(Empty {})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deserializer.deserialize_map(EmptyMapVisitor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serde serialization and deserialization functions that map a `Vec<T>` to a
|
|
||||||
/// `BTreeMap<T, Empty>`.
|
|
||||||
///
|
|
||||||
/// The Matrix spec sometimes specifies lists as hash maps so the list entries
|
|
||||||
/// can be expanded with attributes without breaking compatibility. As that
|
|
||||||
/// would be a breaking change for ruma's event types anyway, we convert them to
|
|
||||||
/// `Vec`s for simplicity, using this module.
|
|
||||||
///
|
|
||||||
/// To be used as `#[serde(with = "vec_as_map_of_empty")]`.
|
|
||||||
pub mod vec_as_map_of_empty {
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|
||||||
|
|
||||||
use super::Empty;
|
|
||||||
|
|
||||||
/// Serialize the given `Vec<T>` as a map of `T => Empty`.
|
|
||||||
#[allow(clippy::ptr_arg)]
|
|
||||||
pub fn serialize<S, T>(vec: &Vec<T>, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
T: Serialize + Eq + Ord,
|
|
||||||
{
|
|
||||||
// FIXME: Don't construct a temporary `BTreeMap`.
|
|
||||||
vec.iter().map(|v| (v, Empty {})).collect::<BTreeMap<_, _>>().serialize(serializer)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialize an object and return the keys as a `Vec<T>`.
|
|
||||||
pub fn deserialize<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
T: Deserialize<'de> + Eq + Ord,
|
|
||||||
{
|
|
||||||
// FIXME: Don't construct a temporary `BTreeMap`.
|
|
||||||
BTreeMap::<T, Empty>::deserialize(deserializer)
|
|
||||||
.map(|hashmap| hashmap.into_iter().map(|(k, _)| k).collect())
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user