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)]
mod tests {
use matches::assert_matches;
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
use super::{
Filter, FilterDefinition, IncomingFilterDefinition, IncomingRoomFilter, RoomEventFilter,
RoomFilter,
Filter, FilterDefinition, IncomingFilterDefinition, IncomingRoomEventFilter,
IncomingRoomFilter, LazyLoadOptions, RoomEventFilter, RoomFilter, UrlFilter,
};
#[test]
@ -428,4 +429,39 @@ mod tests {
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::{
de::{Deserialize, Deserializer, MapAccess, Visitor},
ser::{Serialize, SerializeStruct as _, Serializer},
};
use serde::{ser::SerializeStruct as _, Deserialize, Serialize, Serializer};
/// Specifies options for [lazy-loading membership events][lazy-loading] on
/// supported endpoints
///
/// [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 {
/// Disables lazy-loading of membership events.
Disabled,
@ -52,7 +48,7 @@ impl Serialize for LazyLoadOptions {
state = serializer.serialize_struct("LazyLoad", 1)?;
state.serialize_field("lazy_load_members", &true)?;
}
_ => {
Self::Disabled => {
state = serializer.serialize_struct("LazyLoad", 0)?;
}
}
@ -60,43 +56,21 @@ impl Serialize for LazyLoadOptions {
}
}
struct LazyLoadOptionsVisitor;
impl<'de> Visitor<'de> for LazyLoadOptionsVisitor {
type Value = LazyLoadOptions;
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
})
}
#[derive(Deserialize)]
struct LazyLoadJsonRepr {
lazy_load_members: Option<bool>,
include_redundant_members: Option<bool>,
}
impl<'de> Deserialize<'de> for LazyLoadOptions {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(LazyLoadOptionsVisitor)
impl From<LazyLoadJsonRepr> for LazyLoadOptions {
fn from(opts: LazyLoadJsonRepr) -> Self {
if opts.lazy_load_members.unwrap_or(false) {
Self::Enabled {
include_redundant_members: opts.include_redundant_members.unwrap_or(false),
}
} else {
Self::Disabled
}
}
}