Skip to main content

ruma_common/
to_device.rs

1//! Common types for the Send-To-Device Messaging
2//!
3//! [send-to-device]: https://spec.matrix.org/v1.19/client-server-api/#send-to-device-messaging
4
5use std::{
6    fmt::{Display, Formatter, Result as FmtResult},
7    str::FromStr,
8};
9
10use serde::{
11    Deserialize, Deserializer, Serialize, Serializer,
12    de::{self, Unexpected},
13};
14
15use crate::OwnedDeviceId;
16
17/// Represents one or all of a user's devices.
18#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
19#[allow(clippy::exhaustive_enums)]
20pub enum DeviceIdOrAllDevices {
21    /// Represents a device Id for one of a user's devices.
22    DeviceId(OwnedDeviceId),
23
24    /// Represents all devices for a user.
25    AllDevices,
26}
27
28impl Display for DeviceIdOrAllDevices {
29    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
30        match self {
31            DeviceIdOrAllDevices::DeviceId(device_id) => write!(f, "{device_id}"),
32            DeviceIdOrAllDevices::AllDevices => write!(f, "*"),
33        }
34    }
35}
36
37impl From<OwnedDeviceId> for DeviceIdOrAllDevices {
38    fn from(d: OwnedDeviceId) -> Self {
39        DeviceIdOrAllDevices::DeviceId(d)
40    }
41}
42
43impl TryFrom<&str> for DeviceIdOrAllDevices {
44    type Error = &'static str;
45
46    fn try_from(device_id_or_all_devices: &str) -> Result<Self, Self::Error> {
47        if device_id_or_all_devices.is_empty() {
48            Err("Device identifier cannot be empty")
49        } else if "*" == device_id_or_all_devices {
50            Ok(DeviceIdOrAllDevices::AllDevices)
51        } else {
52            Ok(DeviceIdOrAllDevices::DeviceId(device_id_or_all_devices.into()))
53        }
54    }
55}
56
57impl FromStr for DeviceIdOrAllDevices {
58    type Err = &'static str;
59
60    fn from_str(s: &str) -> Result<Self, Self::Err> {
61        s.try_into()
62    }
63}
64
65impl Serialize for DeviceIdOrAllDevices {
66    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
67    where
68        S: Serializer,
69    {
70        match self {
71            Self::DeviceId(device_id) => device_id.serialize(serializer),
72            Self::AllDevices => serializer.serialize_str("*"),
73        }
74    }
75}
76
77impl<'de> Deserialize<'de> for DeviceIdOrAllDevices {
78    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
79    where
80        D: Deserializer<'de>,
81    {
82        let s = crate::serde::deserialize_cow_str(deserializer)?;
83        DeviceIdOrAllDevices::try_from(s.as_ref()).map_err(|_| {
84            de::Error::invalid_value(Unexpected::Str(&s), &"a valid device identifier or '*'")
85        })
86    }
87}