diff --git a/ruma-events-macros/src/gen.rs b/ruma-events-macros/src/gen.rs index 8dc09837..d6a67c32 100644 --- a/ruma-events-macros/src/gen.rs +++ b/ruma-events-macros/src/gen.rs @@ -153,7 +153,7 @@ impl ToTokens for RumaEvent { } /// Additional key-value pairs not signed by the homeserver. - fn unsigned(&self) -> &serde_json::Map { + fn unsigned(&self) -> &std::collections::BTreeMap { &self.unsigned } } @@ -295,8 +295,8 @@ fn populate_room_event_fields(content_name: Ident, fields: Vec) -> Vec, + #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")] + pub unsigned: std::collections::BTreeMap, }; fields.extend(punctuated_fields.into_iter().map(|p| p.field)); diff --git a/ruma-events-macros/src/lib.rs b/ruma-events-macros/src/lib.rs index 793271b0..19159a1b 100644 --- a/ruma-events-macros/src/lib.rs +++ b/ruma-events-macros/src/lib.rs @@ -112,7 +112,7 @@ mod parse; /// /// /// /// A mapping of `UserId`'s to a collection of `RoomId`'s which are considered /// /// *direct* for that particular user. -/// std::collections::HashMap> +/// std::collections::BTreeMap> /// } /// } /// } diff --git a/src/direct.rs b/src/direct.rs index 1d811fb0..c1b7392e 100644 --- a/src/direct.rs +++ b/src/direct.rs @@ -1,6 +1,6 @@ //! Types for the *m.direct* event. -use std::collections::HashMap; +use std::collections::BTreeMap; use ruma_events_macros::ruma_event; use ruma_identifiers::{RoomId, UserId}; @@ -15,14 +15,14 @@ ruma_event! { /// /// A mapping of `UserId`s to a list of `RoomId`s which are considered *direct* for that /// particular user. - HashMap> + BTreeMap> }, } } #[cfg(test)] mod tests { - use std::collections::HashMap; + use std::collections::BTreeMap; use ruma_identifiers::{RoomId, UserId}; use serde_json::{from_value as from_json_value, json, to_value as to_json_value}; @@ -32,7 +32,7 @@ mod tests { #[test] fn serialization() { - let mut content: DirectEventContent = HashMap::new(); + let mut content: DirectEventContent = BTreeMap::new(); let alice = UserId::new("ruma.io").unwrap(); let room = vec![RoomId::new("ruma.io").unwrap()]; diff --git a/src/event_type.rs b/src/event_type.rs index ee37d978..199bda1a 100644 --- a/src/event_type.rs +++ b/src/event_type.rs @@ -6,7 +6,7 @@ use std::{ use serde::{Deserialize, Serialize}; /// The type of an event. -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] // Cow because deserialization sometimes needs to copy to unescape things #[serde(from = "Cow<'_, str>", into = "String")] pub enum EventType { diff --git a/src/from_raw.rs b/src/from_raw.rs index 95213391..07d27b88 100644 --- a/src/from_raw.rs +++ b/src/from_raw.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, convert::Infallible, fmt::Display}; +use std::{collections::BTreeMap, convert::Infallible, fmt::Display}; use serde::de::DeserializeOwned; @@ -35,7 +35,7 @@ impl FromRaw for serde_json::Value { } } -impl FromRaw for HashMap +impl FromRaw for BTreeMap where Self: DeserializeOwned, { diff --git a/src/key/verification/mac.rs b/src/key/verification/mac.rs index 1aad1d9a..488d2d3f 100644 --- a/src/key/verification/mac.rs +++ b/src/key/verification/mac.rs @@ -1,6 +1,6 @@ //! Types for the *m.key.verification.mac* event. -use std::collections::HashMap; +use std::collections::BTreeMap; use ruma_events_macros::ruma_event; @@ -20,7 +20,7 @@ ruma_event! { /// A map of the key ID to the MAC of the key, using the algorithm in the verification process. /// /// The MAC is encoded as unpadded Base64. - pub mac: HashMap, + pub mac: BTreeMap, /// The MAC of the comma-separated, sorted, list of key IDs given in the `mac` property, encoded /// as unpadded Base64. diff --git a/src/lib.rs b/src/lib.rs index 7ada0346..04121df5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,7 +44,7 @@ //! They have at least the following additional keys: //! * `state_key`, a string which serves as a sort of "sub-type." //! The state key allows a room to persist multiple state events of the same type. -//! You can think of a room's state events as being a `HashMap` where the keys are the tuple +//! You can think of a room's state events as being a `BTreeMap` where the keys are the tuple //! `(event_type, state_key)`. //! * Optionally, `prev_content`, a JSON object containing the `content` object from the //! previous event of the given `(event_type, state_key)` tuple in the given room. @@ -116,6 +116,7 @@ #![allow(clippy::use_self)] use std::{ + collections::BTreeMap, error::Error, fmt::{Debug, Display, Formatter, Result as FmtResult}, time::SystemTime, @@ -127,7 +128,7 @@ use serde::{ ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer, }; -use serde_json::{Map, Value}; +use serde_json::Value; pub use self::{custom::CustomEvent, custom_room::CustomRoomEvent, custom_state::CustomStateEvent}; @@ -317,7 +318,7 @@ impl Error for FromStrError {} /// 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 `HashMap` in Rust code. +/// but it's wasteful to represent it as a `BTreeMap` in Rust code. #[derive(Clone, Debug, PartialEq)] pub struct Empty; @@ -394,7 +395,7 @@ pub trait RoomEvent: Event { fn sender(&self) -> &UserId; /// Additional key-value pairs not signed by the homeserver. - fn unsigned(&self) -> &Map; + fn unsigned(&self) -> &BTreeMap; } /// An event that describes persistent state about a room. @@ -459,13 +460,13 @@ mod custom { } mod custom_room { - use std::time::SystemTime; + use std::{collections::BTreeMap, time::SystemTime}; use super::{Event, EventType, RoomEvent}; use ruma_events_macros::FromRaw; use serde::{Deserialize, Serialize}; - use serde_json::{Map, Value}; + use serde_json::Value; /// A custom room event not covered by the Matrix specification. #[derive(Clone, Debug, FromRaw, PartialEq, Serialize)] @@ -485,8 +486,8 @@ mod custom_room { /// The unique identifier for the user who sent this event. pub sender: ruma_identifiers::UserId, /// Additional key-value pairs not signed by the homeserver. - #[serde(skip_serializing_if = "serde_json::Map::is_empty")] - pub unsigned: Map, + #[serde(skip_serializing_if = "std::collections::BTreeMap::is_empty")] + pub unsigned: BTreeMap, } /// The payload for `CustomRoomEvent`. @@ -532,7 +533,7 @@ mod custom_room { } /// Additional key-value pairs not signed by the homeserver. - fn unsigned(&self) -> &Map { + fn unsigned(&self) -> &BTreeMap { &self.unsigned } } @@ -559,19 +560,19 @@ mod custom_room { pub sender: ruma_identifiers::UserId, /// Additional key-value pairs not signed by the homeserver. #[serde(default)] - pub unsigned: Map, + pub unsigned: BTreeMap, } } } mod custom_state { - use std::time::SystemTime; + use std::{collections::BTreeMap, time::SystemTime}; use super::{Event, EventType, RoomEvent, StateEvent}; use ruma_events_macros::FromRaw; use serde::{Deserialize, Serialize}; - use serde_json::{Map, Value}; + use serde_json::Value; /// A custom state event not covered by the Matrix specification. #[derive(Clone, Debug, FromRaw, PartialEq, Serialize)] @@ -595,8 +596,8 @@ mod custom_state { /// A key that determines which piece of room state the event represents. pub state_key: String, /// Additional key-value pairs not signed by the homeserver. - #[serde(skip_serializing_if = "serde_json::Map::is_empty")] - pub unsigned: Map, + #[serde(skip_serializing_if = "std::collections::BTreeMap::is_empty")] + pub unsigned: BTreeMap, } /// The payload for `CustomStateEvent`. @@ -642,7 +643,7 @@ mod custom_state { } /// Additional key-value pairs not signed by the homeserver. - fn unsigned(&self) -> &Map { + fn unsigned(&self) -> &BTreeMap { &self.unsigned } } @@ -685,7 +686,7 @@ mod custom_state { pub state_key: String, /// Additional key-value pairs not signed by the homeserver. #[serde(default)] - pub unsigned: Map, + pub unsigned: BTreeMap, } } } diff --git a/src/macros.rs b/src/macros.rs index fede51ea..2590f7a8 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -72,7 +72,7 @@ macro_rules! impl_room_event { } /// Additional key-value pairs not signed by the homeserver. - fn unsigned(&self) -> &::serde_json::Map { + fn unsigned(&self) -> &::std::collections::BTreeMap { &self.unsigned } } diff --git a/src/receipt.rs b/src/receipt.rs index 8c63ed22..b0492995 100644 --- a/src/receipt.rs +++ b/src/receipt.rs @@ -1,6 +1,6 @@ //! Types for the *m.receipt* event. -use std::{collections::HashMap, time::SystemTime}; +use std::{collections::BTreeMap, time::SystemTime}; use ruma_events_macros::ruma_event; use ruma_identifiers::{EventId, RoomId, UserId}; @@ -23,7 +23,7 @@ ruma_event! { /// /// A mapping of event ID to a collection of receipts for this event ID. The event ID is the ID of /// the event being acknowledged and *not* an ID for the receipt itself. - HashMap + BTreeMap }, } } @@ -40,7 +40,7 @@ pub struct Receipts { /// A mapping of user ID to receipt. /// /// The user ID is the entity who sent this receipt. -pub type UserReceipts = HashMap; +pub type UserReceipts = BTreeMap; /// An acknowledgement of an event. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] diff --git a/src/room.rs b/src/room.rs index 5b4e35a4..e05ee9ad 100644 --- a/src/room.rs +++ b/src/room.rs @@ -2,7 +2,7 @@ //! //! This module also contains types shared by events in its child namespaces. -use std::collections::HashMap; +use std::collections::BTreeMap; use js_int::UInt; use serde::{Deserialize, Serialize}; @@ -97,7 +97,7 @@ pub struct EncryptedFile { /// A map from an algorithm name to a hash of the ciphertext, encoded as unpadded base64. /// Clients should support the SHA-256 hash, which uses the key sha256. - pub hashes: HashMap, + pub hashes: BTreeMap, /// Version of the encrypted attachments protocol. Must be `v2`. pub v: String, diff --git a/src/room/canonical_alias.rs b/src/room/canonical_alias.rs index 1753580e..f0d2cd48 100644 --- a/src/room/canonical_alias.rs +++ b/src/room/canonical_alias.rs @@ -1,6 +1,7 @@ //! Types for the *m.room.canonical_alias* event. use std::{ + collections::BTreeMap, convert::TryFrom, time::{SystemTime, UNIX_EPOCH}, }; @@ -10,7 +11,7 @@ use serde::{ ser::{Error, SerializeStruct}, Deserialize, Serialize, Serializer, }; -use serde_json::{Map, Value}; +use serde_json::Value; use crate::{util::empty_string_as_none, Event, EventType, FromRaw}; @@ -39,7 +40,7 @@ pub struct CanonicalAliasEvent { pub state_key: String, /// Additional key-value pairs not signed by the homeserver. - pub unsigned: Map, + pub unsigned: BTreeMap, } /// The payload for `CanonicalAliasEvent`. @@ -165,7 +166,7 @@ pub(crate) mod raw { /// Additional key-value pairs not signed by the homeserver. #[serde(default)] - pub unsigned: Map, + pub unsigned: BTreeMap, } /// The payload of a `CanonicalAliasEvent`. @@ -185,12 +186,13 @@ pub(crate) mod raw { #[cfg(test)] mod tests { use std::{ + collections::BTreeMap, convert::TryFrom, time::{Duration, UNIX_EPOCH}, }; use ruma_identifiers::{EventId, RoomAliasId, UserId}; - use serde_json::{from_value as from_json_value, json, to_value as to_json_value, Map}; + use serde_json::{from_value as from_json_value, json, to_value as to_json_value}; use super::{CanonicalAliasEvent, CanonicalAliasEventContent}; use crate::EventResult; @@ -207,7 +209,7 @@ mod tests { room_id: None, sender: UserId::try_from("@carl:example.com").unwrap(), state_key: "".to_string(), - unsigned: Map::new(), + unsigned: BTreeMap::new(), }; let actual = to_json_value(&canonical_alias_event).unwrap(); diff --git a/src/room/encrypted.rs b/src/room/encrypted.rs index 5ebf4626..99b4020b 100644 --- a/src/room/encrypted.rs +++ b/src/room/encrypted.rs @@ -1,11 +1,11 @@ //! Types for the *m.room.encrypted* event. -use std::{collections::HashMap, time::SystemTime}; +use std::{collections::BTreeMap, time::SystemTime}; use js_int::UInt; use ruma_identifiers::{DeviceId, EventId, RoomId, UserId}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use serde_json::{from_value, Map, Value}; +use serde_json::{from_value, Value}; use crate::{Algorithm, EventType, FromRaw}; @@ -34,8 +34,8 @@ pub struct EncryptedEvent { pub sender: UserId, /// Additional key-value pairs not signed by the homeserver. - #[serde(skip_serializing_if = "Map::is_empty")] - pub unsigned: Map, + #[serde(skip_serializing_if = "BTreeMap::is_empty")] + pub unsigned: BTreeMap, } /// The payload for `EncryptedEvent`. @@ -134,7 +134,7 @@ pub(crate) mod raw { /// Additional key-value pairs not signed by the homeserver. #[serde(default)] - pub unsigned: Map, + pub unsigned: BTreeMap, } /// The payload for `EncryptedEvent`. @@ -206,7 +206,7 @@ pub struct OlmV1Curve25519AesSha2Content { pub algorithm: Algorithm, /// A map from the recipient Curve25519 identity key to ciphertext information. - pub ciphertext: HashMap, + pub ciphertext: BTreeMap, /// The Curve25519 key of the sender. pub sender_key: String, diff --git a/src/room/member.rs b/src/room/member.rs index 81433c1c..53dc1cde 100644 --- a/src/room/member.rs +++ b/src/room/member.rs @@ -1,6 +1,6 @@ //! Types for the *m.room.member* event. -use std::collections::HashMap; +use std::collections::BTreeMap; use ruma_events_macros::ruma_event; use ruma_identifiers::UserId; @@ -123,7 +123,7 @@ pub struct SignedContent { /// A single signature from the verifying server, in the format specified by the Signing Events /// section of the server-server API. - pub signatures: HashMap>, + pub signatures: BTreeMap>, /// The token property of the containing third_party_invite object. pub token: String, @@ -227,7 +227,7 @@ mod tests { }; use ruma_identifiers::{EventId, RoomId, UserId}; - use serde_json::{json, Map}; + use serde_json::json; use super::*; use crate::util::serde_json_eq_try_from_raw; @@ -247,7 +247,7 @@ mod tests { room_id: Some(RoomId::try_from("!n8f893n9:example.com").unwrap()), sender: UserId::try_from("@carl:example.com").unwrap(), state_key: "example.com".to_string(), - unsigned: Map::new(), + unsigned: BTreeMap::new(), prev_content: None, }; let json = json!({ @@ -279,7 +279,7 @@ mod tests { room_id: Some(RoomId::try_from("!n8f893n9:example.com").unwrap()), sender: UserId::try_from("@carl:example.com").unwrap(), state_key: "example.com".to_string(), - unsigned: Map::new(), + unsigned: BTreeMap::new(), prev_content: Some(MemberEventContent { avatar_url: None, displayname: None, @@ -335,7 +335,7 @@ mod tests { room_id: Some(RoomId::try_from("!jEsUZKDJdhlrceRyVU:example.org").unwrap()), sender: UserId::try_from("@alice:example.org").unwrap(), state_key: "@alice:example.org".to_string(), - unsigned: Map::new(), + unsigned: BTreeMap::new(), prev_content: None, }; let json = json!({ @@ -390,7 +390,7 @@ mod tests { room_id: Some(RoomId::try_from("!jEsUZKDJdhlrceRyVU:example.org").unwrap()), sender: UserId::try_from("@alice:example.org").unwrap(), state_key: "@alice:example.org".to_string(), - unsigned: Map::new(), + unsigned: BTreeMap::new(), prev_content: Some(MemberEventContent { avatar_url: Some("mxc://example.org/SEsfnsuifSDFSSEF".to_owned()), displayname: Some("Alice Margatroid".to_owned()), diff --git a/src/room/message.rs b/src/room/message.rs index 820723e9..c3083335 100644 --- a/src/room/message.rs +++ b/src/room/message.rs @@ -1,11 +1,11 @@ //! Types for the *m.room.message* event. -use std::time::SystemTime; +use std::{collections::BTreeMap, time::SystemTime}; use js_int::UInt; use ruma_identifiers::{EventId, RoomId, UserId}; use serde::{ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer}; -use serde_json::{from_value, Map, Value}; +use serde_json::{from_value, Value}; use super::{EncryptedFile, ImageInfo, ThumbnailInfo}; use crate::{EventType, FromRaw}; @@ -34,8 +34,8 @@ pub struct MessageEvent { pub sender: UserId, /// Additional key-value pairs not signed by the homeserver. - #[serde(skip_serializing_if = "Map::is_empty")] - pub unsigned: Map, + #[serde(skip_serializing_if = "BTreeMap::is_empty")] + pub unsigned: BTreeMap, } /// The payload for `MessageEvent`. @@ -163,7 +163,7 @@ pub(crate) mod raw { /// Additional key-value pairs not signed by the homeserver. #[serde(default)] - pub unsigned: Map, + pub unsigned: BTreeMap, } /// The payload for `MessageEvent`. diff --git a/src/room/name.rs b/src/room/name.rs index 857acfb2..0fe4c54f 100644 --- a/src/room/name.rs +++ b/src/room/name.rs @@ -1,10 +1,10 @@ //! Types for the *m.room.name* event. -use std::time::SystemTime; +use std::{collections::BTreeMap, time::SystemTime}; use ruma_identifiers::{EventId, RoomId, UserId}; use serde::{Deserialize, Serialize}; -use serde_json::{Map, Value}; +use serde_json::Value; use crate::{util::empty_string_as_none, EventType, InvalidInput, TryFromRaw}; @@ -37,8 +37,8 @@ pub struct NameEvent { pub state_key: String, /// Additional key-value pairs not signed by the homeserver. - #[serde(skip_serializing_if = "Map::is_empty")] - pub unsigned: Map, + #[serde(skip_serializing_if = "BTreeMap::is_empty")] + pub unsigned: BTreeMap, } /// The payload for `NameEvent`. @@ -136,7 +136,7 @@ pub(crate) mod raw { /// Additional key-value pairs not signed by the homeserver. #[serde(default)] - pub unsigned: Map, + pub unsigned: BTreeMap, } /// The payload of a `NameEvent`. @@ -154,13 +154,14 @@ pub(crate) mod raw { #[cfg(test)] mod tests { use std::{ + collections::BTreeMap, convert::TryFrom, iter::FromIterator, time::{Duration, UNIX_EPOCH}, }; use ruma_identifiers::{EventId, RoomId, UserId}; - use serde_json::{from_value as from_json_value, json, to_value as to_json_value, Map}; + use serde_json::{from_value as from_json_value, json, to_value as to_json_value}; use crate::EventResult; @@ -178,7 +179,7 @@ mod tests { room_id: None, sender: UserId::try_from("@carl:example.com").unwrap(), state_key: "".to_string(), - unsigned: Map::new(), + unsigned: BTreeMap::new(), }; let actual = to_json_value(&name_event).unwrap(); diff --git a/src/room/pinned_events.rs b/src/room/pinned_events.rs index 631706f3..ec149691 100644 --- a/src/room/pinned_events.rs +++ b/src/room/pinned_events.rs @@ -17,10 +17,13 @@ ruma_event! { #[cfg(test)] mod tests { - use std::time::{Duration, UNIX_EPOCH}; + use std::{ + collections::BTreeMap, + time::{Duration, UNIX_EPOCH}, + }; use ruma_identifiers::{EventId, RoomId, UserId}; - use serde_json::{to_string, Map}; + use serde_json::to_string; use crate::{ room::pinned_events::{PinnedEventsEvent, PinnedEventsEventContent}, @@ -42,7 +45,7 @@ mod tests { room_id: Some(RoomId::new("example.com").unwrap()), sender: UserId::new("example.com").unwrap(), state_key: "".to_string(), - unsigned: Map::new(), + unsigned: BTreeMap::new(), }; let serialized_event = to_string(&event).unwrap(); diff --git a/src/room/power_levels.rs b/src/room/power_levels.rs index 4b8a0705..e7ae8e1e 100644 --- a/src/room/power_levels.rs +++ b/src/room/power_levels.rs @@ -1,11 +1,11 @@ //! Types for the *m.room.power_levels* event. -use std::{collections::HashMap, time::SystemTime}; +use std::{collections::BTreeMap, time::SystemTime}; use js_int::Int; use ruma_identifiers::{EventId, RoomId, UserId}; use serde::{Deserialize, Serialize}; -use serde_json::{Map, Value}; +use serde_json::Value; use crate::{EventType, FromRaw}; @@ -32,8 +32,8 @@ pub struct PowerLevelsEvent { pub room_id: Option, /// Additional key-value pairs not signed by the homeserver. - #[serde(skip_serializing_if = "Map::is_empty")] - pub unsigned: Map, + #[serde(skip_serializing_if = "BTreeMap::is_empty")] + pub unsigned: BTreeMap, /// The unique identifier for the user who sent this event. pub sender: UserId, @@ -52,8 +52,8 @@ pub struct PowerLevelsEventContent { /// The level required to send specific event types. /// /// This is a mapping from event type to power level required. - #[serde(skip_serializing_if = "HashMap::is_empty")] - pub events: HashMap, + #[serde(skip_serializing_if = "BTreeMap::is_empty")] + pub events: BTreeMap, /// The default level required to send message events. #[serde(skip_serializing_if = "is_power_level_zero")] @@ -78,8 +78,8 @@ pub struct PowerLevelsEventContent { /// The power levels for specific users. /// /// This is a mapping from `user_id` to power level for that user. - #[serde(skip_serializing_if = "HashMap::is_empty")] - pub users: HashMap, + #[serde(skip_serializing_if = "BTreeMap::is_empty")] + pub users: BTreeMap, /// The default power level for every user in the room. #[serde(skip_serializing_if = "is_power_level_zero")] @@ -158,7 +158,7 @@ pub(crate) mod raw { /// Additional key-value pairs not signed by the homeserver. #[serde(default)] - pub unsigned: Map, + pub unsigned: BTreeMap, /// The unique identifier for the user who sent this event. pub sender: UserId, @@ -178,7 +178,7 @@ pub(crate) mod raw { /// /// This is a mapping from event type to power level required. #[serde(default)] - pub events: HashMap, + pub events: BTreeMap, /// The default level required to send message events. #[serde(default)] @@ -204,7 +204,7 @@ pub(crate) mod raw { /// /// This is a mapping from `user_id` to power level for that user. #[serde(default)] - pub users: HashMap, + pub users: BTreeMap, /// The default power level for every user in the room. #[serde(default)] @@ -263,15 +263,15 @@ fn is_power_level_zero(l: &Int) -> bool { #[cfg(test)] mod tests { use std::{ - collections::HashMap, + collections::BTreeMap, convert::TryFrom, time::{Duration, UNIX_EPOCH}, }; use js_int::Int; - use maplit::hashmap; + use maplit::btreemap; use ruma_identifiers::{EventId, RoomId, UserId}; - use serde_json::{json, to_value as to_json_value, Map}; + use serde_json::{json, to_value as to_json_value}; use super::{ default_power_level, NotificationPowerLevels, PowerLevelsEvent, PowerLevelsEventContent, @@ -285,13 +285,13 @@ mod tests { let power_levels_event = PowerLevelsEvent { content: PowerLevelsEventContent { ban: default, - events: HashMap::new(), + events: BTreeMap::new(), events_default: Int::from(0), invite: default, kick: default, redact: default, state_default: default, - users: HashMap::new(), + users: BTreeMap::new(), users_default: Int::from(0), notifications: NotificationPowerLevels::default(), }, @@ -299,7 +299,7 @@ mod tests { origin_server_ts: UNIX_EPOCH + Duration::from_millis(1), prev_content: None, room_id: None, - unsigned: Map::new(), + unsigned: BTreeMap::new(), sender: UserId::try_from("@carl:example.com").unwrap(), state_key: "".to_string(), }; @@ -323,7 +323,7 @@ mod tests { let power_levels_event = PowerLevelsEvent { content: PowerLevelsEventContent { ban: Int::from(23), - events: hashmap! { + events: btreemap! { EventType::Dummy => Int::from(23) }, events_default: Int::from(23), @@ -331,7 +331,7 @@ mod tests { kick: Int::from(23), redact: Int::from(23), state_default: Int::from(23), - users: hashmap! { + users: btreemap! { user.clone() => Int::from(23) }, users_default: Int::from(23), @@ -344,7 +344,7 @@ mod tests { prev_content: Some(PowerLevelsEventContent { // Make just one field different so we at least know they're two different objects. ban: Int::from(42), - events: hashmap! { + events: btreemap! { EventType::Dummy => Int::from(42) }, events_default: Int::from(42), @@ -352,7 +352,7 @@ mod tests { kick: Int::from(42), redact: Int::from(42), state_default: Int::from(42), - users: hashmap! { + users: btreemap! { user.clone() => Int::from(42) }, users_default: Int::from(42), diff --git a/src/room/server_acl.rs b/src/room/server_acl.rs index 130ccc4b..963f0071 100644 --- a/src/room/server_acl.rs +++ b/src/room/server_acl.rs @@ -1,10 +1,10 @@ //! Types for the *m.room.server_acl* event. -use std::time::SystemTime; +use std::{collections::BTreeMap, time::SystemTime}; use ruma_identifiers::{EventId, RoomId, UserId}; use serde::{Deserialize, Serialize}; -use serde_json::{Map, Value}; +use serde_json::Value; use crate::{util::default_true, EventType, FromRaw}; @@ -37,8 +37,8 @@ pub struct ServerAclEvent { pub state_key: String, /// Additional key-value pairs not signed by the homeserver. - #[serde(skip_serializing_if = "Map::is_empty")] - pub unsigned: Map, + #[serde(skip_serializing_if = "BTreeMap::is_empty")] + pub unsigned: BTreeMap, } /// The payload for `ServerAclEvent`. @@ -129,7 +129,7 @@ pub(crate) mod raw { /// Additional key-value pairs not signed by the homeserver. #[serde(default)] - pub unsigned: Map, + pub unsigned: BTreeMap, /// The unique identifier for the user who sent this event. pub sender: UserId, diff --git a/src/tag.rs b/src/tag.rs index 6c59d994..65b17517 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -1,6 +1,6 @@ //! Types for the *m.tag* event. -use std::collections::HashMap; +use std::collections::BTreeMap; use ruma_events_macros::ruma_event; use serde::{Deserialize, Serialize}; @@ -12,7 +12,7 @@ ruma_event! { event_type: "m.tag", content: { /// A map of tag names to tag info. - pub tags: HashMap, + pub tags: BTreeMap, }, } } diff --git a/src/util.rs b/src/util.rs index 5a6e8494..80bb7cc6 100644 --- a/src/util.rs +++ b/src/util.rs @@ -72,7 +72,7 @@ where } } -/// Serde serialization and deserialization functions that map a `Vec` to a `HashMap`. +/// Serde serialization and deserialization functions that map a `Vec` to a `BTreeMap`. /// /// 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 @@ -80,28 +80,30 @@ where /// /// To be used as `#[serde(with = "vec_as_map_of_empty")]`. pub mod vec_as_map_of_empty { - use crate::Empty; + use std::collections::BTreeMap; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; - use std::{collections::HashMap, hash::Hash}; + + use crate::Empty; #[allow(clippy::ptr_arg)] pub fn serialize(vec: &Vec, serializer: S) -> Result where S: Serializer, - T: Serialize + Hash + Eq, + T: Serialize + Eq + Ord, { vec.iter() .map(|v| (v, Empty)) - .collect::>() + .collect::>() .serialize(serializer) } pub fn deserialize<'de, D, T>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, - T: Deserialize<'de> + Hash + Eq, + T: Deserialize<'de> + Eq + Ord, { - HashMap::::deserialize(deserializer) + BTreeMap::::deserialize(deserializer) .map(|hashmap| hashmap.into_iter().map(|(k, _)| k).collect()) } } diff --git a/tests/ruma_events_macros.rs b/tests/ruma_events_macros.rs index a1061e98..a7742229 100644 --- a/tests/ruma_events_macros.rs +++ b/tests/ruma_events_macros.rs @@ -1,5 +1,5 @@ use std::{ - collections::HashMap, + collections::BTreeMap, convert::TryFrom, time::{Duration, UNIX_EPOCH}, }; @@ -37,7 +37,7 @@ mod common_case { room_id: None, sender: UserId::try_from("@carl:example.com").unwrap(), state_key: "example.com".to_string(), - unsigned: serde_json::Map::new(), + unsigned: std::collections::BTreeMap::new(), }; let json = json!({ "content": { @@ -66,7 +66,7 @@ mod common_case { room_id: Some(RoomId::try_from("!n8f893n9:example.com").unwrap()), sender: UserId::try_from("@carl:example.com").unwrap(), state_key: "example.com".to_string(), - unsigned: serde_json::Map::new(), + unsigned: std::collections::BTreeMap::new(), }; let json = json!({ "content": { @@ -183,7 +183,7 @@ mod type_alias { /// /// A mapping of `UserId`'s to a collection of `RoomId`'s which are considered /// *direct* for that particular user. - HashMap> + BTreeMap> } } }