ruma_client_api/
dehydrated_device.rs

1//! Endpoints for managing dehydrated devices.
2
3use ruma_common::serde::StringEnum;
4use serde::{Deserialize, Serialize};
5
6use crate::PrivOwnedStr;
7
8pub mod delete_dehydrated_device;
9pub mod get_dehydrated_device;
10pub mod get_events;
11pub mod put_dehydrated_device;
12
13/// Data for a dehydrated device.
14#[derive(Clone, Debug, Deserialize, Serialize)]
15#[serde(try_from = "Helper", into = "Helper")]
16#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
17pub enum DehydratedDeviceData {
18    /// The `org.matrix.msc3814.v1.olm` variant of a dehydrated device.
19    V1(DehydratedDeviceV1),
20    /// The `org.matrix.msc3814.v2` variant of a dehydrated device.
21    V2(DehydratedDeviceV2),
22}
23
24impl DehydratedDeviceData {
25    /// Get the algorithm this dehydrated device uses.
26    pub fn algorithm(&self) -> DeviceDehydrationAlgorithm {
27        match self {
28            DehydratedDeviceData::V1(_) => DeviceDehydrationAlgorithm::V1,
29            DehydratedDeviceData::V2(_) => DeviceDehydrationAlgorithm::V2,
30        }
31    }
32}
33
34/// The `org.matrix.msc3814.v1.olm` variant of a dehydrated device.
35#[derive(Clone, Debug)]
36#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
37pub struct DehydratedDeviceV1 {
38    /// The pickle of the `Olm` account of the device.
39    ///
40    /// The pickle will contain the private parts of the long-term identity keys of the device as
41    /// well as a collection of one-time keys.
42    pub device_pickle: String,
43}
44
45impl DehydratedDeviceV1 {
46    /// Create a [`DehydratedDeviceV1`] struct from a device pickle.
47    pub fn new(device_pickle: String) -> Self {
48        Self { device_pickle }
49    }
50}
51
52/// The `org.matrix.msc3814.v2` variant of a dehydrated device.
53#[derive(Clone, Debug)]
54#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
55pub struct DehydratedDeviceV2 {
56    /// The pickle of the `Olm` account of the device.
57    ///
58    /// The pickle will contain the private parts of the long-term identity keys of the device as
59    /// well as a collection of one-time keys.
60    pub device_pickle: String,
61    /// The nonce used to encrypt the pickle.
62    pub nonce: String,
63}
64
65impl DehydratedDeviceV2 {
66    /// Create a [`DehydratedDeviceV2`] struct from a device pickle.
67    pub fn new(device_pickle: String, nonce: String) -> Self {
68        Self { device_pickle, nonce }
69    }
70}
71
72/// The algorithms used for dehydrated devices.
73#[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))]
74#[derive(Clone, PartialEq, Eq, StringEnum)]
75#[non_exhaustive]
76pub enum DeviceDehydrationAlgorithm {
77    /// The `org.matrix.msc3814.v1.olm` device dehydration algorithm.
78    #[ruma_enum(rename = "org.matrix.msc3814.v1.olm")]
79    V1,
80    /// The `org.matrix.msc3814.v2` device dehydration algorithm.
81    #[ruma_enum(rename = "org.matrix.msc3814.v2")]
82    V2,
83    #[doc(hidden)]
84    _Custom(PrivOwnedStr),
85}
86
87#[derive(Deserialize, Serialize)]
88struct Helper {
89    algorithm: DeviceDehydrationAlgorithm,
90    device_pickle: String,
91    #[serde(skip_serializing_if = "Option::is_none")]
92    nonce: Option<String>,
93}
94
95impl TryFrom<Helper> for DehydratedDeviceData {
96    type Error = serde_json::Error;
97
98    fn try_from(value: Helper) -> Result<Self, Self::Error> {
99        match value.algorithm {
100            DeviceDehydrationAlgorithm::V1 => Ok(DehydratedDeviceData::V1(DehydratedDeviceV1 {
101                device_pickle: value.device_pickle,
102            })),
103            DeviceDehydrationAlgorithm::V2 => Ok(DehydratedDeviceData::V2(DehydratedDeviceV2 {
104                device_pickle: value.device_pickle,
105                nonce: value
106                    .nonce
107                    .ok_or(serde::de::Error::custom("Missing nonce in v2 dehydrated device."))?,
108            })),
109            _ => Err(serde::de::Error::custom("Unsupported device dehydration algorithm.")),
110        }
111    }
112}
113
114impl From<DehydratedDeviceData> for Helper {
115    fn from(value: DehydratedDeviceData) -> Self {
116        let algorithm = value.algorithm();
117
118        match value {
119            DehydratedDeviceData::V1(d) => {
120                Self { algorithm, device_pickle: d.device_pickle, nonce: None }
121            }
122            DehydratedDeviceData::V2(d) => {
123                Self { algorithm, device_pickle: d.device_pickle, nonce: Some(d.nonce) }
124            }
125        }
126    }
127}