Update ruma_serde to 0.1.2
This commit is contained in:
parent
fd5527da78
commit
0d305d8f24
@ -16,7 +16,7 @@ edition = "2018"
|
||||
js_int = { version = "0.1.5", features = ["serde"] }
|
||||
ruma-events-macros = { path = "ruma-events-macros", version = "=0.21.0-beta.1" }
|
||||
ruma-identifiers = "0.16.0"
|
||||
ruma-serde = "0.1.0"
|
||||
ruma-serde = "0.1.2"
|
||||
serde = { version = "1.0.106", features = ["derive"] }
|
||||
serde_json = { version = "1.0.52", features = ["raw_value"] }
|
||||
|
||||
|
@ -64,10 +64,10 @@ impl From<Algorithm> for String {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ruma_serde::test::serde_json_eq;
|
||||
use serde_json::json;
|
||||
|
||||
use super::*;
|
||||
use crate::util::serde_json_eq;
|
||||
|
||||
#[test]
|
||||
fn serialize_and_deserialize_from_display_form() {
|
||||
|
@ -1,8 +1,7 @@
|
||||
//! Types for the *m.dummy* event.
|
||||
|
||||
use ruma_events_macros::ruma_event;
|
||||
|
||||
use crate::Empty;
|
||||
use ruma_serde::empty::Empty;
|
||||
|
||||
ruma_event! {
|
||||
/// This event type is used to indicate new Olm sessions for end-to-end encryption.
|
||||
|
58
src/empty.rs
58
src/empty.rs
@ -1,58 +0,0 @@
|
||||
use std::fmt::{self, Formatter};
|
||||
|
||||
use serde::{
|
||||
de::{Deserialize, Deserializer, MapAccess, Visitor},
|
||||
ser::{Serialize, SerializeMap, Serializer},
|
||||
};
|
||||
|
||||
use crate::FromRaw;
|
||||
|
||||
/// A meaningless value that serializes to an empty JSON object.
|
||||
///
|
||||
/// This type is used in a few places where the Matrix specification requires an empty JSON object,
|
||||
/// but it's wasteful to represent it as a `BTreeMap` in Rust code.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Empty;
|
||||
|
||||
impl Serialize for Empty {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_map(Some(0))?.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Empty {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct EmptyMapVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for EmptyMapVisitor {
|
||||
type Value = Empty;
|
||||
|
||||
fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "an object/map")
|
||||
}
|
||||
|
||||
fn visit_map<A>(self, _map: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: MapAccess<'de>,
|
||||
{
|
||||
Ok(Empty)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_map(EmptyMapVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRaw for Empty {
|
||||
type Raw = Self;
|
||||
|
||||
fn from_raw(raw: Self) -> Self {
|
||||
raw
|
||||
}
|
||||
}
|
@ -269,10 +269,10 @@ impl From<EventType> for String {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ruma_serde::test::serde_json_eq;
|
||||
use serde_json::json;
|
||||
|
||||
use super::*;
|
||||
use crate::util::serde_json_eq;
|
||||
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
#[test]
|
||||
|
@ -27,6 +27,14 @@ pub trait TryFromRaw: Sized {
|
||||
fn try_from_raw(_: Self::Raw) -> Result<Self, Self::Err>;
|
||||
}
|
||||
|
||||
impl FromRaw for ruma_serde::empty::Empty {
|
||||
type Raw = Self;
|
||||
|
||||
fn from_raw(raw: Self) -> Self {
|
||||
raw
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRaw for serde_json::Value {
|
||||
type Raw = Self;
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
use ruma_identifiers::UserId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{util::vec_as_map_of_empty, EventType, FromRaw};
|
||||
use crate::{EventType, FromRaw};
|
||||
|
||||
/// A list of users to ignore.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
@ -27,7 +27,7 @@ impl FromRaw for IgnoredUserListEvent {
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
pub struct IgnoredUserListEventContent {
|
||||
/// A list of users to ignore.
|
||||
#[serde(with = "vec_as_map_of_empty")]
|
||||
#[serde(with = "ruma_serde::vec_as_map_of_empty")]
|
||||
pub ignored_users: Vec<UserId>,
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ pub(crate) mod raw {
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct IgnoredUserListEventContent {
|
||||
/// A list of users to ignore.
|
||||
#[serde(with = "vec_as_map_of_empty")]
|
||||
#[serde(with = "ruma_serde::vec_as_map_of_empty")]
|
||||
pub ignored_users: Vec<UserId>,
|
||||
}
|
||||
}
|
||||
|
@ -122,16 +122,15 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use self::room::redaction::RedactionEvent;
|
||||
|
||||
pub use self::{
|
||||
custom::{CustomEvent, CustomRoomEvent, CustomStateEvent},
|
||||
empty::Empty,
|
||||
};
|
||||
pub use self::custom::{CustomEvent, CustomRoomEvent, CustomStateEvent};
|
||||
|
||||
#[deprecated = "Use ruma_serde::empty::Empty directly instead."]
|
||||
pub use ruma_serde::empty::Empty;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
mod algorithm;
|
||||
mod empty;
|
||||
mod error;
|
||||
mod event_type;
|
||||
mod from_raw;
|
||||
|
@ -13,7 +13,7 @@ use serde::{
|
||||
};
|
||||
use serde_json::{from_value, Value};
|
||||
|
||||
use crate::{util::default_true, FromStrError};
|
||||
use crate::FromStrError;
|
||||
|
||||
ruma_event! {
|
||||
/// Describes all push rules for a user.
|
||||
@ -230,13 +230,12 @@ impl<'de> Deserialize<'de> for Action {
|
||||
|
||||
/// Values for the `set_tweak` action.
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
||||
#[serde(tag = "set_tweak")]
|
||||
#[serde(tag = "set_tweak", rename_all = "lowercase")]
|
||||
pub enum Tweak {
|
||||
/// A string representing the sound to be played when this notification arrives.
|
||||
///
|
||||
/// A value of "default" means to play a default sound. A device may choose to alert the user by
|
||||
/// some other means if appropriate, eg. vibration.
|
||||
#[serde(rename = "sound")]
|
||||
Sound {
|
||||
/// The sound to be played.
|
||||
value: String,
|
||||
@ -249,10 +248,9 @@ pub enum Tweak {
|
||||
/// event occurred. If a `highlight` tweak is given with no value, its value is defined to be
|
||||
/// `true`. If no highlight tweak is given at all then the value of `highlight` is defined to be
|
||||
/// `false`.
|
||||
#[serde(rename = "highlight")]
|
||||
Highlight {
|
||||
/// Whether or not the message should be highlighted.
|
||||
#[serde(default = "default_true")]
|
||||
#[serde(default = "ruma_serde::default_true")]
|
||||
value: bool,
|
||||
},
|
||||
}
|
||||
|
@ -3,8 +3,6 @@
|
||||
use ruma_events_macros::ruma_event;
|
||||
use ruma_identifiers::RoomAliasId;
|
||||
|
||||
use crate::util::empty_string_as_none;
|
||||
|
||||
ruma_event! {
|
||||
/// Informs the room as to which alias is the canonical one.
|
||||
CanonicalAliasEvent {
|
||||
@ -16,7 +14,7 @@ ruma_event! {
|
||||
/// Rooms with `alias: None` should be treated the same as a room
|
||||
/// with no canonical alias.
|
||||
#[serde(
|
||||
default, deserialize_with = "empty_string_as_none",
|
||||
default, deserialize_with = "ruma_serde::empty_string_as_none",
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub alias: Option<RoomAliasId>,
|
||||
|
@ -6,8 +6,6 @@ use ruma_events_macros::ruma_event;
|
||||
use ruma_identifiers::{EventId, RoomId, RoomVersionId, UserId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::util::default_true;
|
||||
|
||||
ruma_event! {
|
||||
/// This is the first event in a room and cannot be changed. It acts as the root of all other
|
||||
/// events.
|
||||
@ -19,8 +17,7 @@ ruma_event! {
|
||||
pub creator: UserId,
|
||||
|
||||
/// Whether or not this room's data should be transferred to other homeservers.
|
||||
#[serde(rename = "m.federate")]
|
||||
#[serde(default = "default_true")]
|
||||
#[serde(rename = "m.federate", default = "ruma_serde::default_true")]
|
||||
pub federate: bool,
|
||||
|
||||
/// The version of the room. Defaults to "1" if the key does not exist.
|
||||
|
@ -5,7 +5,7 @@ use std::time::SystemTime;
|
||||
use ruma_identifiers::{EventId, RoomId, UserId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{util::empty_string_as_none, EventType, InvalidInput, TryFromRaw, UnsignedData};
|
||||
use crate::{EventType, InvalidInput, TryFromRaw, UnsignedData};
|
||||
|
||||
/// A human-friendly room name designed to be displayed to the end-user.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
@ -144,8 +144,7 @@ pub(crate) mod raw {
|
||||
/// The name of the room. This MUST NOT exceed 255 bytes.
|
||||
// The spec says "A room with an m.room.name event with an absent, null, or empty name field
|
||||
// should be treated the same as a room with no m.room.name event."
|
||||
#[serde(default)]
|
||||
#[serde(deserialize_with = "empty_string_as_none")]
|
||||
#[serde(default, deserialize_with = "ruma_serde::empty_string_as_none")]
|
||||
pub(crate) name: Option<String>,
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use std::time::SystemTime;
|
||||
use ruma_identifiers::{EventId, RoomId, UserId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{util::default_true, EventType, FromRaw, UnsignedData};
|
||||
use crate::{EventType, FromRaw, UnsignedData};
|
||||
|
||||
/// An event to indicate which servers are permitted to participate in the room.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
@ -49,7 +49,7 @@ pub struct ServerAclEventContent {
|
||||
/// This is strongly recommended to be set to false as servers running with IP literal names are
|
||||
/// strongly discouraged in order to require legitimate homeservers to be backed by a valid
|
||||
/// registered domain name.
|
||||
#[serde(default = "default_true")]
|
||||
#[serde(default = "ruma_serde::default_true")]
|
||||
pub allow_ip_literals: bool,
|
||||
|
||||
/// The server names to allow in the room, excluding any port information. Wildcards may be used
|
||||
@ -146,7 +146,7 @@ pub(crate) mod raw {
|
||||
/// This is strongly recommended to be set to false as servers running with IP literal names
|
||||
/// are strongly discouraged in order to require legitimate homeservers to be backed by a
|
||||
/// valid registered domain name.
|
||||
#[serde(default = "default_true")]
|
||||
#[serde(default = "ruma_serde::default_true")]
|
||||
pub allow_ip_literals: bool,
|
||||
|
||||
/// The server names to allow in the room, excluding any port information. Wildcards may be
|
||||
|
82
src/util.rs
82
src/util.rs
@ -1,9 +1,6 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use serde::{
|
||||
de::{Deserialize, DeserializeOwned, IntoDeserializer},
|
||||
Serialize,
|
||||
};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::{EventJson, TryFromRaw};
|
||||
@ -45,83 +42,6 @@ where
|
||||
.map_err(serde_json_error_to_generic_de_error)
|
||||
}
|
||||
|
||||
/// Serde deserialization decorator to map empty Strings to None,
|
||||
/// and forward non-empty Strings to the Deserialize implementation for T.
|
||||
/// Useful for the typical
|
||||
/// "A room with an X event with an absent, null, or empty Y field
|
||||
/// should be treated the same as a room with no such event."
|
||||
/// formulation in the spec.
|
||||
///
|
||||
/// To be used like this:
|
||||
/// `#[serde(deserialize_with = "empty_string_as_none"]`
|
||||
/// Relevant serde issue: https://github.com/serde-rs/serde/issues/1425
|
||||
pub fn empty_string_as_none<'de, D, T>(de: D) -> Result<Option<T>, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
T: serde::Deserialize<'de>,
|
||||
{
|
||||
let opt = Option::<String>::deserialize(de)?;
|
||||
// TODO: Switch to and remove this attribute `opt.as_deref()` once MSRV is >= 1.40
|
||||
#[allow(clippy::option_as_ref_deref, clippy::unknown_clippy_lints)]
|
||||
let opt = opt.as_ref().map(String::as_str);
|
||||
match opt {
|
||||
None | Some("") => Ok(None),
|
||||
// If T = String, like in m.room.name, the second deserialize is actually superfluous.
|
||||
// TODO: optimize that somehow?
|
||||
Some(s) => T::deserialize(s.into_deserializer()).map(Some),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 crate::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,
|
||||
{
|
||||
vec.iter()
|
||||
.map(|v| (v, Empty))
|
||||
.collect::<BTreeMap<_, _>>()
|
||||
.serialize(serializer)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
T: Deserialize<'de> + Eq + Ord,
|
||||
{
|
||||
BTreeMap::<T, Empty>::deserialize(deserializer)
|
||||
.map(|hashmap| hashmap.into_iter().map(|(k, _)| k).collect())
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to default the `bool` fields to `true` during deserialization.
|
||||
pub fn default_true() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn serde_json_eq<T>(de: T, se: serde_json::Value)
|
||||
where
|
||||
T: Clone + Debug + PartialEq + Serialize + DeserializeOwned,
|
||||
{
|
||||
assert_eq!(se, serde_json::to_value(de.clone()).unwrap());
|
||||
assert_eq!(de, serde_json::from_value(se).unwrap());
|
||||
}
|
||||
|
||||
// This would be #[cfg(test)] if it wasn't used from external tests
|
||||
pub fn serde_json_eq_try_from_raw<T>(de: T, se: serde_json::Value)
|
||||
where
|
||||
|
Loading…
x
Reference in New Issue
Block a user