events: Change IgnoredUserListEventContent to use a map of empty structs
This commit is contained in:
parent
2500e8f8fa
commit
eecae05721
@ -26,6 +26,8 @@ Breaking changes:
|
|||||||
* `FromHttpResponseError<E>::Server` now contains `E` instead of `ServerError<E>`
|
* `FromHttpResponseError<E>::Server` now contains `E` instead of `ServerError<E>`
|
||||||
* `ServerError<E>` has been removed
|
* `ServerError<E>` has been removed
|
||||||
* `MatrixError` is now an enum with the `Json` variant containing the previous fields
|
* `MatrixError` is now an enum with the `Json` variant containing the previous fields
|
||||||
|
* Change the `ignored_users` field of `IgnoredUserListEventContent` to a map of empty structs, to
|
||||||
|
allow eventual fields to be added, as intended by the spec
|
||||||
|
|
||||||
Improvements:
|
Improvements:
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
//!
|
//!
|
||||||
//! [`m.ignored_user_list`]: https://spec.matrix.org/v1.4/client-server-api/#mignored_user_list
|
//! [`m.ignored_user_list`]: https://spec.matrix.org/v1.4/client-server-api/#mignored_user_list
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use ruma_macros::EventContent;
|
use ruma_macros::EventContent;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -14,103 +16,32 @@ use crate::OwnedUserId;
|
|||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[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 map of users to ignore.
|
||||||
#[serde(with = "vec_as_map_of_empty")]
|
///
|
||||||
pub ignored_users: Vec<OwnedUserId>,
|
/// As [`IgnoredUser`] is currently empty, only the user IDs are useful and
|
||||||
|
/// can be accessed with the `.keys()` and `into_keys()` iterators.
|
||||||
|
pub ignored_users: BTreeMap<OwnedUserId, IgnoredUser>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IgnoredUserListEventContent {
|
impl IgnoredUserListEventContent {
|
||||||
/// Creates a new `IgnoredUserListEventContent` from the given user IDs.
|
/// Creates a new `IgnoredUserListEventContent` from the given map of ignored user.
|
||||||
pub fn new(ignored_users: Vec<OwnedUserId>) -> Self {
|
pub fn new(ignored_users: BTreeMap<OwnedUserId, IgnoredUser>) -> Self {
|
||||||
Self { ignored_users }
|
Self { ignored_users }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mod vec_as_map_of_empty {
|
/// Creates a new `IgnoredUserListEventContent` from the given list of users.
|
||||||
use std::{fmt, marker::PhantomData};
|
pub fn users(ignored_users: impl IntoIterator<Item = OwnedUserId>) -> Self {
|
||||||
|
Self::new(ignored_users.into_iter().map(|id| (id, IgnoredUser {})).collect())
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Details about an ignored user.
|
||||||
|
///
|
||||||
|
/// This is currently empty.
|
||||||
|
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||||
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
|
pub struct IgnoredUser {}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use assert_matches::assert_matches;
|
use assert_matches::assert_matches;
|
||||||
@ -125,9 +56,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn serialization() {
|
fn serialization() {
|
||||||
let ignored_user_list_event = GlobalAccountDataEvent {
|
let ignored_user_list_event = GlobalAccountDataEvent {
|
||||||
content: IgnoredUserListEventContent {
|
content: IgnoredUserListEventContent::users(vec![
|
||||||
ignored_users: vec![user_id!("@carl:example.com").to_owned()],
|
user_id!("@carl:example.com").to_owned()
|
||||||
},
|
]),
|
||||||
};
|
};
|
||||||
|
|
||||||
let json = json!({
|
let json = json!({
|
||||||
@ -157,6 +88,9 @@ mod tests {
|
|||||||
from_json_value::<AnyGlobalAccountDataEvent>(json),
|
from_json_value::<AnyGlobalAccountDataEvent>(json),
|
||||||
Ok(AnyGlobalAccountDataEvent::IgnoredUserList(ev)) => ev
|
Ok(AnyGlobalAccountDataEvent::IgnoredUserList(ev)) => ev
|
||||||
);
|
);
|
||||||
assert_eq!(ev.content.ignored_users, vec![user_id!("@carl:example.com")]);
|
assert_eq!(
|
||||||
|
ev.content.ignored_users.keys().collect::<Vec<_>>(),
|
||||||
|
vec![user_id!("@carl:example.com")]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user