common: Replace BTreeSet by IndexSet in push::Ruleset.

Keeps the JSON ordering for priority.

IndexSet are hashed by `rule_id` so its uniqueness is enforced.

A rule can be fetched by its `rule_id`.
This commit is contained in:
Kévin Commaille 2021-03-21 10:50:40 +01:00 committed by Jonas Platte
parent acb7fdd647
commit 22f7f28e1b
4 changed files with 35 additions and 29 deletions

View File

@ -3,6 +3,7 @@
Breaking changes: Breaking changes:
* Update set of conversion trait implementations for enums * Update set of conversion trait implementations for enums
* Replace `BTreeSet` by `IndexSet` in `push::Ruleset`.
* … (there's a lot more, but this changelog was not kept up to date; PRs to * … (there's a lot more, but this changelog was not kept up to date; PRs to
improve it are welcome) improve it are welcome)

View File

@ -17,6 +17,7 @@ ruma-identifiers = { version = "=0.18.0-alpha.1", path = "../ruma-identifiers" }
ruma-serde = { version = "0.3.0", path = "../ruma-serde" } ruma-serde = { version = "0.3.0", path = "../ruma-serde" }
serde = { version = "1.0.118", features = ["derive"] } serde = { version = "1.0.118", features = ["derive"] }
serde_json = { version = "1.0.60", features = ["raw_value"] } serde_json = { version = "1.0.60", features = ["raw_value"] }
indexmap = { version = "1.6.2", features = ["serde-1"] }
[dev-dependencies] [dev-dependencies]
matches = "0.1.8" matches = "0.1.8"

View File

@ -6,13 +6,13 @@
//! //!
//! Push rules are grouped in `RuleSet`s, and are grouped in five kinds (for //! Push rules are grouped in `RuleSet`s, and are grouped in five kinds (for
//! more details about the different kind of rules, see the `Ruleset` documentation, //! more details about the different kind of rules, see the `Ruleset` documentation,
//! or the specification). These five kinds are: //! or the specification). These five kinds are, by order of priority:
//! //!
//! - content rules
//! - override rules //! - override rules
//! - underride rules //! - content rules
//! - room rules //! - room rules
//! - sender rules //! - sender rules
//! - underride rules
//! //!
//! Each of these kind of rule has a corresponding type that is //! Each of these kind of rule has a corresponding type that is
//! just a wrapper around another type: //! just a wrapper around another type:
@ -34,8 +34,12 @@
//! There is also the `AnyPushRule` type that is the most generic form of push rule, with all //! There is also the `AnyPushRule` type that is the most generic form of push rule, with all
//! the possible fields. //! the possible fields.
use std::collections::btree_set::{BTreeSet, IntoIter as BTreeSetIter}; use std::hash::{Hash, Hasher};
use indexmap::{
set::{IndexSet, IntoIter as IndexSetIter},
Equivalent,
};
use ruma_serde::StringEnum; use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -58,24 +62,24 @@ pub use self::{
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct Ruleset { pub struct Ruleset {
/// These rules configure behavior for (unencrypted) messages that match certain patterns. /// These rules configure behavior for (unencrypted) messages that match certain patterns.
pub content: BTreeSet<ContentPushRule>, pub content: IndexSet<ContentPushRule>,
/// These user-configured rules are given the highest priority. /// These user-configured rules are given the highest priority.
/// ///
/// This field is named `override_` instead of `override` because the latter is a reserved /// This field is named `override_` instead of `override` because the latter is a reserved
/// keyword in Rust. /// keyword in Rust.
#[serde(rename = "override")] #[serde(rename = "override")]
pub override_: BTreeSet<OverridePushRule>, pub override_: IndexSet<OverridePushRule>,
/// These rules change the behavior of all messages for a given room. /// These rules change the behavior of all messages for a given room.
pub room: BTreeSet<RoomPushRule>, pub room: IndexSet<RoomPushRule>,
/// These rules configure notification behavior for messages from a specific Matrix user ID. /// These rules configure notification behavior for messages from a specific Matrix user ID.
pub sender: BTreeSet<SenderPushRule>, pub sender: IndexSet<SenderPushRule>,
/// These rules are identical to override rules, but have a lower priority than `content`, /// These rules are identical to override rules, but have a lower priority than `content`,
/// `room` and `sender` rules. /// `room` and `sender` rules.
pub underride: BTreeSet<UnderridePushRule>, pub underride: IndexSet<UnderridePushRule>,
} }
impl Ruleset { impl Ruleset {
@ -97,11 +101,11 @@ impl Ruleset {
/// Iterator type for `Ruleset` /// Iterator type for `Ruleset`
#[derive(Debug)] #[derive(Debug)]
pub struct RulesetIter { pub struct RulesetIter {
content: BTreeSetIter<ContentPushRule>, content: IndexSetIter<ContentPushRule>,
override_: BTreeSetIter<OverridePushRule>, override_: IndexSetIter<OverridePushRule>,
room: BTreeSetIter<RoomPushRule>, room: IndexSetIter<RoomPushRule>,
sender: BTreeSetIter<SenderPushRule>, sender: IndexSetIter<SenderPushRule>,
underride: BTreeSetIter<UnderridePushRule>, underride: IndexSetIter<UnderridePushRule>,
} }
impl Iterator for RulesetIter { impl Iterator for RulesetIter {
@ -180,17 +184,11 @@ macro_rules! rulekind {
} }
// The following trait are needed to be able to make // The following trait are needed to be able to make
// a BTreeSet of the new type // an IndexSet of the new type
impl Ord for $name { impl Hash for $name {
fn cmp(&self, other: &Self) -> core::cmp::Ordering { fn hash<H: Hasher>(&self, state: &mut H) {
self.0.rule_id.cmp(&other.0.rule_id) self.0.rule_id.hash(state);
}
}
impl PartialOrd for $name {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
} }
} }
@ -201,6 +199,12 @@ macro_rules! rulekind {
} }
impl Eq for $name {} impl Eq for $name {}
impl Equivalent<$name> for str {
fn equivalent(&self, key: &$name) -> bool {
self == key.0.rule_id
}
}
}; };
} }

View File

@ -1,7 +1,7 @@
///! Constructors for [predefined push rules]. ///! Constructors for [predefined push rules].
///! ///!
///! [predefined push rules]: https://matrix.org/docs/spec/client_server/r0.6.1#predefined-rules ///! [predefined push rules]: https://matrix.org/docs/spec/client_server/r0.6.1#predefined-rules
use maplit::btreeset; use indexmap::indexset;
use ruma_identifiers::UserId; use ruma_identifiers::UserId;
use super::{ use super::{
@ -20,9 +20,9 @@ impl Ruleset {
/// user's ID (for instance those to send notifications when they are mentioned). /// user's ID (for instance those to send notifications when they are mentioned).
pub fn server_default(user_id: &UserId) -> Self { pub fn server_default(user_id: &UserId) -> Self {
Self { Self {
content: btreeset![ContentPushRule::contains_user_name(user_id)], content: indexset![ContentPushRule::contains_user_name(user_id)],
#[cfg(feature = "unstable-pre-spec")] #[cfg(feature = "unstable-pre-spec")]
override_: btreeset![ override_: indexset![
OverridePushRule::master(), OverridePushRule::master(),
OverridePushRule::suppress_notices(), OverridePushRule::suppress_notices(),
OverridePushRule::invite_for_me(user_id), OverridePushRule::invite_for_me(user_id),
@ -33,7 +33,7 @@ impl Ruleset {
OverridePushRule::reaction(), OverridePushRule::reaction(),
], ],
#[cfg(not(feature = "unstable-pre-spec"))] #[cfg(not(feature = "unstable-pre-spec"))]
override_: btreeset![ override_: indexset![
OverridePushRule::master(), OverridePushRule::master(),
OverridePushRule::suppress_notices(), OverridePushRule::suppress_notices(),
OverridePushRule::invite_for_me(user_id), OverridePushRule::invite_for_me(user_id),
@ -42,7 +42,7 @@ impl Ruleset {
OverridePushRule::tombstone(), OverridePushRule::tombstone(),
OverridePushRule::roomnotif(), OverridePushRule::roomnotif(),
], ],
underride: btreeset![ underride: indexset![
UnderridePushRule::call(), UnderridePushRule::call(),
UnderridePushRule::encrypted_room_one_to_one(), UnderridePushRule::encrypted_room_one_to_one(),
UnderridePushRule::room_one_to_one(), UnderridePushRule::room_one_to_one(),