client-api: Fix deserialization of LazyLoadOptions when serde(flatten)ed

This commit is contained in:
Jonas Platte 2020-12-07 13:23:55 +01:00
parent ff78ab87dd
commit c274431949
No known key found for this signature in database
GPG Key ID: 7D261D771D915378
2 changed files with 55 additions and 45 deletions

View File

@ -390,11 +390,12 @@ can_be_empty!(IncomingRoomFilter);
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use matches::assert_matches;
use serde_json::{from_value as from_json_value, json, to_value as to_json_value}; use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
use super::{ use super::{
Filter, FilterDefinition, IncomingFilterDefinition, IncomingRoomFilter, RoomEventFilter, Filter, FilterDefinition, IncomingFilterDefinition, IncomingRoomEventFilter,
RoomFilter, IncomingRoomFilter, LazyLoadOptions, RoomEventFilter, RoomFilter, UrlFilter,
}; };
#[test] #[test]
@ -428,4 +429,39 @@ mod tests {
Ok(()) Ok(())
} }
#[test]
fn issue_218() -> Result<(), serde_json::Error> {
let obj = json!({
"lazy_load_members": true,
"filter_json": { "contains_url": true, "types": ["m.room.message"] },
"types": ["m.room.message"],
"not_types": [],
"rooms": null,
"not_rooms": [],
"senders": null,
"not_senders": [],
"contains_url": true,
});
assert_matches!(
from_json_value(obj)?,
IncomingRoomEventFilter {
types: Some(types),
not_types,
rooms: None,
not_rooms,
senders: None,
not_senders,
limit: None,
url_filter: Some(UrlFilter::EventsWithUrl),
lazy_load_options: LazyLoadOptions::Enabled { include_redundant_members: false },
} if types == vec!["m.room.message".to_owned()]
&& not_types.is_empty()
&& not_rooms.is_empty()
&& not_senders.is_empty()
);
Ok(())
}
} }

View File

@ -1,15 +1,11 @@
use std::fmt; use serde::{ser::SerializeStruct as _, Deserialize, Serialize, Serializer};
use serde::{
de::{Deserialize, Deserializer, MapAccess, Visitor},
ser::{Serialize, SerializeStruct as _, Serializer},
};
/// Specifies options for [lazy-loading membership events][lazy-loading] on /// Specifies options for [lazy-loading membership events][lazy-loading] on
/// supported endpoints /// supported endpoints
/// ///
/// [lazy-loading]: https://matrix.org/docs/spec/client_server/r0.6.0#lazy-loading-room-members /// [lazy-loading]: https://matrix.org/docs/spec/client_server/r0.6.0#lazy-loading-room-members
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize)]
#[serde(from = "LazyLoadJsonRepr")]
pub enum LazyLoadOptions { pub enum LazyLoadOptions {
/// Disables lazy-loading of membership events. /// Disables lazy-loading of membership events.
Disabled, Disabled,
@ -52,7 +48,7 @@ impl Serialize for LazyLoadOptions {
state = serializer.serialize_struct("LazyLoad", 1)?; state = serializer.serialize_struct("LazyLoad", 1)?;
state.serialize_field("lazy_load_members", &true)?; state.serialize_field("lazy_load_members", &true)?;
} }
_ => { Self::Disabled => {
state = serializer.serialize_struct("LazyLoad", 0)?; state = serializer.serialize_struct("LazyLoad", 0)?;
} }
} }
@ -60,43 +56,21 @@ impl Serialize for LazyLoadOptions {
} }
} }
struct LazyLoadOptionsVisitor; #[derive(Deserialize)]
struct LazyLoadJsonRepr {
impl<'de> Visitor<'de> for LazyLoadOptionsVisitor { lazy_load_members: Option<bool>,
type Value = LazyLoadOptions; include_redundant_members: Option<bool>,
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("Lazy load options")
}
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
where
M: MapAccess<'de>,
{
let mut lazy_load_members = false;
let mut include_redundant_members = false;
while let Some((key, value)) = access.next_entry::<String, bool>()? {
match &*key {
"lazy_load_members" => lazy_load_members = value,
"include_redundant_members" => include_redundant_members = value,
_ => {}
};
}
Ok(if lazy_load_members {
LazyLoadOptions::Enabled { include_redundant_members }
} else {
LazyLoadOptions::Disabled
})
}
} }
impl<'de> Deserialize<'de> for LazyLoadOptions { impl From<LazyLoadJsonRepr> for LazyLoadOptions {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn from(opts: LazyLoadJsonRepr) -> Self {
where if opts.lazy_load_members.unwrap_or(false) {
D: Deserializer<'de>, Self::Enabled {
{ include_redundant_members: opts.include_redundant_members.unwrap_or(false),
deserializer.deserialize_map(LazyLoadOptionsVisitor) }
} else {
Self::Disabled
}
} }
} }