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 constructors for `RoomMessageEventContent`
|
||||
* Remove `serde::vec_as_map_of_empty` from the public API
|
||||
|
||||
# 0.10.3
|
||||
|
||||
|
@ -15,7 +15,7 @@ use crate::OwnedUserId;
|
||||
#[ruma_event(type = "m.ignored_user_list", kind = GlobalAccountData)]
|
||||
pub struct IgnoredUserListEventContent {
|
||||
/// 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>,
|
||||
}
|
||||
|
||||
@ -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)]
|
||||
mod tests {
|
||||
use assert_matches::assert_matches;
|
||||
|
@ -13,7 +13,6 @@ mod buf;
|
||||
pub mod can_be_empty;
|
||||
mod cow;
|
||||
pub mod duration;
|
||||
mod empty;
|
||||
pub mod json_string;
|
||||
mod raw;
|
||||
pub mod single_element_seq;
|
||||
@ -26,7 +25,6 @@ pub use self::{
|
||||
buf::{json_to_buf, slice_to_buf},
|
||||
can_be_empty::{is_empty, CanBeEmpty},
|
||||
cow::deserialize_cow_str,
|
||||
empty::vec_as_map_of_empty,
|
||||
raw::Raw,
|
||||
strings::{
|
||||
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