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