From e8bec10c6d94b1a8229270f595e28dd12c58b79c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= Date: Fri, 11 Nov 2022 14:25:18 +0100 Subject: [PATCH] push: Make SimplePushRule generic over the type of the rule_id --- crates/ruma-client-api/src/push.rs | 28 ++++++-- .../ruma-client-api/src/push/set_pushrule.rs | 2 + crates/ruma-common/CHANGELOG.md | 1 + crates/ruma-common/src/push.rs | 71 +++++++++++-------- crates/ruma-common/src/push/iter.rs | 30 ++++---- 5 files changed, 85 insertions(+), 47 deletions(-) diff --git a/crates/ruma-client-api/src/push.rs b/crates/ruma-client-api/src/push.rs index 0ce23975..b8510b45 100644 --- a/crates/ruma-client-api/src/push.rs +++ b/crates/ruma-client-api/src/push.rs @@ -60,9 +60,13 @@ pub struct PushRule { pub pattern: Option, } -impl From for PushRule { - fn from(push_rule: SimplePushRule) -> Self { +impl From> for PushRule +where + T: Into, +{ + fn from(push_rule: SimplePushRule) -> Self { let SimplePushRule { actions, default, enabled, rule_id, .. } = push_rule; + let rule_id = rule_id.into(); Self { actions, default, enabled, rule_id, conditions: None, pattern: None } } } @@ -81,9 +85,13 @@ impl From for PushRule { } } -impl From for PushRule { - fn from(init: SimplePushRuleInit) -> Self { +impl From> for PushRule +where + T: Into, +{ + fn from(init: SimplePushRuleInit) -> Self { let SimplePushRuleInit { actions, default, enabled, rule_id } = init; + let rule_id = rule_id.into(); Self { actions, default, enabled, rule_id, pattern: None, conditions: None } } } @@ -102,10 +110,16 @@ impl From for PushRule { } } -impl From for SimplePushRule { - fn from(push_rule: PushRule) -> Self { +impl TryFrom for SimplePushRule +where + T: TryFrom, +{ + type Error = >::Error; + + fn try_from(push_rule: PushRule) -> Result { let PushRule { actions, default, enabled, rule_id, .. } = push_rule; - SimplePushRuleInit { actions, default, enabled, rule_id }.into() + let rule_id = T::try_from(rule_id)?; + Ok(SimplePushRuleInit { actions, default, enabled, rule_id }.into()) } } diff --git a/crates/ruma-client-api/src/push/set_pushrule.rs b/crates/ruma-client-api/src/push/set_pushrule.rs index 69eff243..9be64360 100644 --- a/crates/ruma-client-api/src/push/set_pushrule.rs +++ b/crates/ruma-client-api/src/push/set_pushrule.rs @@ -175,11 +175,13 @@ pub mod v3 { RuleKind::Sender => { let SimpleRequestBody { actions } = serde_json::from_slice(request.body().as_ref())?; + let rule_id = rule_id.try_into()?; NewPushRule::Sender(NewSimplePushRule::new(rule_id, actions)) } RuleKind::Room => { let SimpleRequestBody { actions } = serde_json::from_slice(request.body().as_ref())?; + let rule_id = rule_id.try_into()?; NewPushRule::Room(NewSimplePushRule::new(rule_id, actions)) } RuleKind::Content => { diff --git a/crates/ruma-common/CHANGELOG.md b/crates/ruma-common/CHANGELOG.md index d7bb4b2d..8815e9c2 100644 --- a/crates/ruma-common/CHANGELOG.md +++ b/crates/ruma-common/CHANGELOG.md @@ -28,6 +28,7 @@ Breaking changes: * `MatrixError` is now an enum with the `Json` variant containing the previous fields * Change the `ignored_users` field of `IgnoredUserListEventContent` to a map of empty structs, to allow eventual fields to be added, as intended by the spec +* Make `SimplePushRule` and associated types generic over the expected type of the `rule_id` Improvements: diff --git a/crates/ruma-common/src/push.rs b/crates/ruma-common/src/push.rs index 08ee1986..3203ee57 100644 --- a/crates/ruma-common/src/push.rs +++ b/crates/ruma-common/src/push.rs @@ -25,7 +25,7 @@ use tracing::instrument; use crate::{ serde::{Raw, StringEnum}, - PrivOwnedStr, + OwnedRoomId, OwnedUserId, PrivOwnedStr, }; mod action; @@ -63,10 +63,10 @@ pub struct Ruleset { pub override_: IndexSet, /// These rules change the behavior of all messages for a given room. - pub room: IndexSet, + pub room: IndexSet>, /// These rules configure notification behavior for messages from a specific Matrix user ID. - pub sender: IndexSet, + pub sender: IndexSet>, /// These rules are identical to override rules, but have a lower priority than `content`, /// `room` and `sender` rules. @@ -320,7 +320,7 @@ impl Ruleset { /// `SimplePushRule::from` / `.into()`. #[derive(Clone, Debug, Deserialize, Serialize)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] -pub struct SimplePushRule { +pub struct SimplePushRule { /// Actions to determine if and how a notification is delivered for events matching this rule. pub actions: Vec, @@ -331,7 +331,9 @@ pub struct SimplePushRule { pub enabled: bool, /// The ID of this rule. - pub rule_id: String, + /// + /// This is generally the Matrix ID of the entity that it applies to. + pub rule_id: T, } /// Initial set of fields of `SimplePushRule`. @@ -340,7 +342,7 @@ pub struct SimplePushRule { /// (non-breaking) release of the Matrix specification. #[derive(Debug)] #[allow(clippy::exhaustive_structs)] -pub struct SimplePushRuleInit { +pub struct SimplePushRuleInit { /// Actions to determine if and how a notification is delivered for events matching this rule. pub actions: Vec, @@ -351,11 +353,13 @@ pub struct SimplePushRuleInit { pub enabled: bool, /// The ID of this rule. - pub rule_id: String, + /// + /// This is generally the Matrix ID of the entity that it applies to. + pub rule_id: T, } -impl From for SimplePushRule { - fn from(init: SimplePushRuleInit) -> Self { +impl From> for SimplePushRule { + fn from(init: SimplePushRuleInit) -> Self { let SimplePushRuleInit { actions, default, enabled, rule_id } = init; Self { actions, default, enabled, rule_id } } @@ -364,23 +368,32 @@ impl From for SimplePushRule { // The following trait are needed to be able to make // an IndexSet of the type -impl Hash for SimplePushRule { +impl Hash for SimplePushRule +where + T: Hash, +{ fn hash(&self, state: &mut H) { self.rule_id.hash(state); } } -impl PartialEq for SimplePushRule { +impl PartialEq for SimplePushRule +where + T: PartialEq, +{ fn eq(&self, other: &Self) -> bool { self.rule_id == other.rule_id } } -impl Eq for SimplePushRule {} +impl Eq for SimplePushRule where T: Eq {} -impl Equivalent for str { - fn equivalent(&self, key: &SimplePushRule) -> bool { - self == key.rule_id +impl Equivalent> for str +where + T: AsRef, +{ + fn equivalent(&self, key: &SimplePushRule) -> bool { + self == key.rule_id.as_ref() } } @@ -668,10 +681,10 @@ pub enum NewPushRule { Content(NewPatternedPushRule), /// Room-specific rules. - Room(NewSimplePushRule), + Room(NewSimplePushRule), /// Sender-specific rules. - Sender(NewSimplePushRule), + Sender(NewSimplePushRule), /// Lowest priority rules. Underride(NewConditionalPushRule), @@ -694,8 +707,8 @@ impl NewPushRule { match self { NewPushRule::Override(r) => &r.rule_id, NewPushRule::Content(r) => &r.rule_id, - NewPushRule::Room(r) => &r.rule_id, - NewPushRule::Sender(r) => &r.rule_id, + NewPushRule::Room(r) => r.rule_id.as_ref(), + NewPushRule::Sender(r) => r.rule_id.as_ref(), NewPushRule::Underride(r) => &r.rule_id, } } @@ -704,24 +717,26 @@ impl NewPushRule { /// A simple push rule to update or create. #[derive(Clone, Debug, Deserialize, Serialize)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] -pub struct NewSimplePushRule { +pub struct NewSimplePushRule { /// The ID of this rule. - pub rule_id: String, + /// + /// This is generally the Matrix ID of the entity that it applies to. + pub rule_id: T, /// Actions to determine if and how a notification is delivered for events matching this /// rule. pub actions: Vec, } -impl NewSimplePushRule { +impl NewSimplePushRule { /// Creates a `NewSimplePushRule` with the given ID and actions. - pub fn new(rule_id: String, actions: Vec) -> Self { + pub fn new(rule_id: T, actions: Vec) -> Self { Self { rule_id, actions } } } -impl From for SimplePushRule { - fn from(new_rule: NewSimplePushRule) -> Self { +impl From> for SimplePushRule { + fn from(new_rule: NewSimplePushRule) -> Self { let NewSimplePushRule { rule_id, actions } = new_rule; Self { actions, default: false, enabled: true, rule_id } } @@ -1002,7 +1017,7 @@ mod tests { actions: vec![Action::DontNotify], default: false, enabled: false, - rule_id: "!roomid:server.name".into(), + rule_id: room_id!("!roomid:server.name").to_owned(), }; let rule_value: JsonValue = to_json_value(rule).unwrap(); @@ -1471,7 +1486,7 @@ mod tests { actions: vec![Action::Notify], default: false, enabled: true, - rule_id: "@rantanplan:server.name".into(), + rule_id: user_id!("@rantanplan:server.name").to_owned(), }; set.sender.insert(sender); @@ -1482,7 +1497,7 @@ mod tests { actions: vec![Action::DontNotify], default: false, enabled: true, - rule_id: "!dm:server.name".into(), + rule_id: room_id!("!dm:server.name").to_owned(), }; set.room.insert(room); diff --git a/crates/ruma-common/src/push/iter.rs b/crates/ruma-common/src/push/iter.rs index e976fa8f..62ad7e1a 100644 --- a/crates/ruma-common/src/push/iter.rs +++ b/crates/ruma-common/src/push/iter.rs @@ -4,6 +4,7 @@ use super::{ condition, Action, ConditionalPushRule, FlattenedJson, PatternedPushRule, PushConditionRoomCtx, Ruleset, SimplePushRule, }; +use crate::{OwnedRoomId, OwnedUserId}; /// The kinds of push rules that are available. #[derive(Clone, Debug)] @@ -16,10 +17,10 @@ pub enum AnyPushRule { Content(PatternedPushRule), /// Room-specific rules. - Room(SimplePushRule), + Room(SimplePushRule), /// Sender-specific rules. - Sender(SimplePushRule), + Sender(SimplePushRule), /// Lowest priority rules. Underride(ConditionalPushRule), @@ -68,8 +69,8 @@ impl AnyPushRule { pub struct RulesetIntoIter { content: IndexSetIntoIter, override_: IndexSetIntoIter, - room: IndexSetIntoIter, - sender: IndexSetIntoIter, + room: IndexSetIntoIter>, + sender: IndexSetIntoIter>, underride: IndexSetIntoIter, } @@ -113,10 +114,10 @@ pub enum AnyPushRuleRef<'a> { Content(&'a PatternedPushRule), /// Room-specific rules. - Room(&'a SimplePushRule), + Room(&'a SimplePushRule), /// Sender-specific rules. - Sender(&'a SimplePushRule), + Sender(&'a SimplePushRule), /// Lowest priority rules. Underride(&'a ConditionalPushRule), @@ -162,8 +163,8 @@ impl<'a> AnyPushRuleRef<'a> { Self::Override(rule) => &rule.rule_id, Self::Underride(rule) => &rule.rule_id, Self::Content(rule) => &rule.rule_id, - Self::Room(rule) => &rule.rule_id, - Self::Sender(rule) => &rule.rule_id, + Self::Room(rule) => rule.rule_id.as_ref(), + Self::Sender(rule) => rule.rule_id.as_ref(), } } @@ -184,11 +185,16 @@ impl<'a> AnyPushRuleRef<'a> { Self::Content(rule) => rule.applies_to("content.body", event, context), Self::Room(rule) => { rule.enabled - && condition::check_event_match(event, "room_id", &rule.rule_id, context) + && condition::check_event_match( + event, + "room_id", + rule.rule_id.as_ref(), + context, + ) } Self::Sender(rule) => { rule.enabled - && condition::check_event_match(event, "sender", &rule.rule_id, context) + && condition::check_event_match(event, "sender", rule.rule_id.as_ref(), context) } } } @@ -199,8 +205,8 @@ impl<'a> AnyPushRuleRef<'a> { pub struct RulesetIter<'a> { content: IndexSetIter<'a, PatternedPushRule>, override_: IndexSetIter<'a, ConditionalPushRule>, - room: IndexSetIter<'a, SimplePushRule>, - sender: IndexSetIter<'a, SimplePushRule>, + room: IndexSetIter<'a, SimplePushRule>, + sender: IndexSetIter<'a, SimplePushRule>, underride: IndexSetIter<'a, ConditionalPushRule>, }