sync_events/get_message_events: ser/de filters to string

This commit is contained in:
Ragotzy.devin 2020-04-14 07:44:16 -04:00 committed by GitHub
parent d94279efaf
commit 9b5b906868
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 108 additions and 28 deletions

View File

@ -47,8 +47,12 @@ ruma_api! {
#[ruma_api(query)]
pub limit: Option<UInt>,
/// A RoomEventFilter to filter returned events with.
#[serde(skip_serializing_if = "Option::is_none")]
#[ruma_api(query)]
#[serde(
with = "crate::serde::json_string",
default,
skip_serializing_if = "Option::is_none"
)]
pub filter: Option<RoomEventFilter>,
}
@ -75,3 +79,80 @@ pub enum Direction {
#[serde(rename = "f")]
Forward,
}
#[cfg(test)]
mod tests {
use super::{Direction, Request};
use std::convert::{TryFrom, TryInto};
use ruma_identifiers::RoomId;
use crate::r0::filter::{LazyLoadOptions, RoomEventFilter};
#[test]
fn test_serialize_some_room_event_filter() {
let room_id = RoomId::try_from("!roomid:example.org").unwrap();
let filter = RoomEventFilter {
lazy_load_options: LazyLoadOptions::Enabled {
include_redundant_members: true,
},
rooms: Some(vec![room_id.clone()]),
not_rooms: vec!["room".into(), "room2".into(), "room3".into()],
not_types: vec!["type".into()],
..Default::default()
};
let req = Request {
room_id,
from: "token".into(),
to: Some("token2".into()),
dir: Direction::Backward,
limit: Some(js_int::UInt::min_value()),
filter: Some(filter),
};
let request: http::Request<Vec<u8>> = req.try_into().unwrap();
assert_eq!(
"from=token&to=token2&dir=b&limit=0&filter=%7B%22not_types%22%3A%5B%22type%22%5D%2C%22not_rooms%22%3A%5B%22room%22%2C%22room2%22%2C%22room3%22%5D%2C%22rooms%22%3A%5B%22%21roomid%3Aexample.org%22%5D%2C%22lazy_load_members%22%3Atrue%2C%22include_redundant_members%22%3Atrue%7D",
request.uri().query().unwrap()
);
}
#[test]
fn test_serialize_none_room_event_filter() {
let room_id = RoomId::try_from("!roomid:example.org").unwrap();
let req = Request {
room_id,
from: "token".into(),
to: Some("token2".into()),
dir: Direction::Backward,
limit: Some(js_int::UInt::min_value()),
filter: None,
};
let request: http::Request<Vec<u8>> = req.try_into().unwrap();
assert_eq!(
"from=token&to=token2&dir=b&limit=0",
request.uri().query().unwrap(),
);
}
#[test]
fn test_serialize_default_room_event_filter() {
let room_id = RoomId::try_from("!roomid:example.org").unwrap();
let req = Request {
room_id,
from: "token".into(),
to: Some("token2".into()),
dir: Direction::Backward,
limit: Some(js_int::UInt::min_value()),
filter: Some(RoomEventFilter::default()),
};
let request: http::Request<Vec<u8>> = req.try_into().unwrap();
assert_eq!(
"from=token&to=token2&dir=b&limit=0&filter=%7B%7D",
request.uri().query().unwrap(),
);
}
}

View File

@ -122,39 +122,13 @@ pub enum Filter {
// FilterDefinition is the first variant, JSON decoding is attempted first which is almost
// functionally equivalent to looking at whether the first symbol is a '{' as the spec says.
// (there are probably some corner cases like leading whitespace)
#[serde(with = "filter_def_serde")]
#[serde(with = "crate::serde::json_string")]
/// A complete filter definition serialized to JSON.
FilterDefinition(FilterDefinition),
/// The ID of a filter saved on the server.
FilterId(String),
}
/// Serialization and deserialization logic for filter definitions.
mod filter_def_serde {
use serde::{de::Error as _, ser::Error as _, Deserialize, Deserializer, Serializer};
use crate::r0::filter::FilterDefinition;
/// Serialization logic for filter definitions.
pub fn serialize<S>(filter_def: &FilterDefinition, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let string = serde_json::to_string(filter_def).map_err(S::Error::custom)?;
serializer.serialize_str(&string)
}
/// Deserialization logic for filter definitions.
pub fn deserialize<'de, D>(deserializer: D) -> Result<FilterDefinition, D::Error>
where
D: Deserializer<'de>,
{
let filter_str = <&str>::deserialize(deserializer)?;
serde_json::from_str(filter_str).map_err(D::Error::custom)
}
}
/// Updates to rooms.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct Rooms {

View File

@ -1,6 +1,7 @@
//! Modules to hold functions for de-/serializing remote types
pub mod duration;
pub mod json_string;
pub fn is_default<T: Default + PartialEq>(val: &T) -> bool {
val == &T::default()

24
src/serde/json_string.rs Normal file
View File

@ -0,0 +1,24 @@
//! De-/serialization functions to and from json strings, allows the type to be used as a query string.
use serde::{
de::{Deserialize, DeserializeOwned, Deserializer, Error as _},
ser::{Error as _, Serialize, Serializer},
};
pub fn serialize<T, S>(filter: T, serializer: S) -> Result<S::Ok, S::Error>
where
T: Serialize,
S: Serializer,
{
let json = serde_json::to_string(&filter).map_err(S::Error::custom)?;
serializer.serialize_str(&json)
}
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
T: DeserializeOwned,
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
serde_json::from_str(&s).map_err(D::Error::custom)
}