1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15+ use std:: fmt;
16+
1517use ruma:: {
1618 events:: {
17- AnyMessageLikeEventContent , AnyTimelineEvent , MessageLikeEventType , StateEventType ,
18- TimelineEventType ,
19+ AnyMessageLikeEventContent , AnyTimelineEvent , AnyToDeviceEvent , MessageLikeEventType ,
20+ StateEventType , TimelineEventType , ToDeviceEventType ,
1921 } ,
2022 serde:: Raw ,
2123} ;
@@ -34,6 +36,8 @@ pub enum Filter {
3436 MessageLike ( MessageLikeEventFilter ) ,
3537 /// Filter for state events.
3638 State ( StateEventFilter ) ,
39+ /// Filter for to device events.
40+ ToDevice ( ToDeviceEventFilter ) ,
3741}
3842
3943impl Filter {
@@ -44,6 +48,7 @@ impl Filter {
4448 match self {
4549 Self :: MessageLike ( filter) => filter. matches ( filter_input) ,
4650 Self :: State ( filter) => filter. matches ( filter_input) ,
51+ Self :: ToDevice ( filter) => filter. matches ( filter_input) ,
4752 }
4853 }
4954 /// Returns the event type that this filter is configured to match.
@@ -54,6 +59,7 @@ impl Filter {
5459 match self {
5560 Self :: MessageLike ( filter) => filter. filter_event_type ( ) ,
5661 Self :: State ( filter) => filter. filter_event_type ( ) ,
62+ Self :: ToDevice ( filter) => filter. event_type . to_string ( ) ,
5763 }
5864 }
5965}
@@ -126,14 +132,43 @@ impl StateEventFilter {
126132 }
127133}
128134
135+ /// Filter for to-device events.
136+ #[ derive( Clone , Debug ) ]
137+ #[ cfg_attr( test, derive( PartialEq ) ) ]
138+ pub struct ToDeviceEventFilter {
139+ /// The event type this to-device-filter filters for.
140+ pub event_type : ToDeviceEventType ,
141+ }
142+
143+ impl ToDeviceEventFilter {
144+ /// Create a new `ToDeviceEventFilter` with the given event type.
145+ pub fn new ( event_type : ToDeviceEventType ) -> Self {
146+ Self { event_type }
147+ }
148+ }
149+
150+ impl ToDeviceEventFilter {
151+ fn matches ( & self , filter_input : & FilterInput ) -> bool {
152+ matches ! ( filter_input, FilterInput :: ToDevice ( f_in) if f_in. event_type == self . event_type)
153+ }
154+ }
155+
156+ impl fmt:: Display for ToDeviceEventFilter {
157+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
158+ write ! ( f, "{}" , self . event_type)
159+ }
160+ }
161+
129162// Filter input:
130163
131- /// The input data for the filter. This can either be constructed from a
132- /// [`Raw<AnyTimelineEvent>`] or a [`SendEventRequest`].
164+ /// The input data for the filter. This can be constructed from a
165+ /// [`Raw<AnyTimelineEvent>`], a [`SendEventRequest`] or a [`Raw<AnyToDeviceEvent>`]
166+ /// or using the FilterInput constructors.
133167#[ derive( Debug ) ]
134168pub enum FilterInput {
135169 State ( FilterInputState ) ,
136170 MessageLike ( FilterInputMessageLike ) ,
171+ ToDevice ( FilterInputToDevice ) ,
137172}
138173
139174impl FilterInput {
@@ -207,6 +242,20 @@ impl TryFrom<Raw<AnyTimelineEvent>> for FilterInput {
207242 }
208243}
209244
245+ #[ derive( Debug , Deserialize ) ]
246+ pub struct FilterInputToDevice {
247+ #[ serde( rename = "type" ) ]
248+ pub ( super ) event_type : ToDeviceEventType ,
249+ }
250+
251+ /// Create a filter input of type [`FilterInput::ToDevice`]`.
252+ impl TryFrom < Raw < AnyToDeviceEvent > > for FilterInput {
253+ type Error = serde_json:: Error ;
254+ fn try_from ( raw_event : Raw < AnyToDeviceEvent > ) -> Result < Self , Self :: Error > {
255+ raw_event. deserialize_as :: < FilterInputToDevice > ( ) . map ( FilterInput :: ToDevice )
256+ }
257+ }
258+
210259impl From < & SendEventRequest > for FilterInput {
211260 fn from ( request : & SendEventRequest ) -> Self {
212261 match & request. state_key {
@@ -243,7 +292,9 @@ mod tests {
243292 use super :: {
244293 Filter , FilterInput , FilterInputMessageLike , MessageLikeEventFilter , StateEventFilter ,
245294 } ;
246- use crate :: widget:: filter:: MessageLikeFilterEventContent ;
295+ use crate :: widget:: filter:: {
296+ FilterInputToDevice , MessageLikeFilterEventContent , ToDeviceEventFilter ,
297+ } ;
247298
248299 fn message_event ( event_type : MessageLikeEventType ) -> FilterInput {
249300 FilterInput :: MessageLike ( FilterInputMessageLike { event_type, content : Default :: default ( ) } )
@@ -424,4 +475,12 @@ mod tests {
424475 assert ! ( !room_message_filter( )
425476 . matches( & FilterInput :: message_like( MessageLikeEventType :: Reaction . to_string( ) ) ) ) ;
426477 }
478+
479+ #[ test]
480+ fn test_to_device_filter_does_match ( ) {
481+ let f = Filter :: ToDevice ( ToDeviceEventFilter :: new ( "my.custom.to.device" . into ( ) ) ) ;
482+ assert ! ( f. matches( & FilterInput :: ToDevice ( FilterInputToDevice {
483+ event_type: "my.custom.to.device" . into( ) ,
484+ } ) ) ) ;
485+ }
427486}
0 commit comments