ruwuma/ruma-client-api/src/r0/capabilities/get_capabilities.rs
2021-02-15 15:32:42 +01:00

189 lines
5.7 KiB
Rust

//! [GET /_matrix/client/r0/capabilities](https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-capabilities)
use std::{borrow::Cow, collections::BTreeMap};
use maplit::btreemap;
use ruma_api::ruma_api;
use ruma_identifiers::RoomVersionId;
use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize};
use serde_json::{from_value as from_json_value, to_value as to_json_value, Value as JsonValue};
ruma_api! {
metadata: {
description: "Gets information about the server's supported feature set and other relevant capabilities.",
method: GET,
name: "get_capabilities",
path: "/_matrix/client/r0/capabilities",
rate_limited: true,
authentication: AccessToken
}
#[derive(Default)]
request: {}
response: {
/// The capabilities the server supports
pub capabilities: Capabilities,
}
error: crate::Error
}
impl Request {
/// Creates an empty `Request`.
pub fn new() -> Self {
Self
}
}
impl Response {
/// Creates a new `Response` with the given capabilities.
pub fn new(capabilities: Capabilities) -> Self {
Self { capabilities }
}
}
impl From<Capabilities> for Response {
fn from(capabilities: Capabilities) -> Self {
Self::new(capabilities)
}
}
/// Contains information about all the capabilities that the server supports.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct Capabilities {
/// Capability to indicate if the user can change their password.
#[serde(
rename = "m.change_password",
default,
skip_serializing_if = "ChangePasswordCapability::is_default"
)]
pub change_password: ChangePasswordCapability,
/// The room versions the server supports.
#[serde(
rename = "m.room_versions",
default,
skip_serializing_if = "RoomVersionsCapability::is_default"
)]
pub room_versions: RoomVersionsCapability,
/// Any other custom capabilities that the server supports outside of the specification,
/// labeled using the Java package naming convention and stored as arbitrary JSON values.
#[serde(flatten)]
custom_capabilities: BTreeMap<String, JsonValue>,
}
impl Capabilities {
/// Creates empty `Capabilities`.
pub fn new() -> Self {
Default::default()
}
/// Returns value of the given capability.
pub fn get(&self, capability: &str) -> serde_json::Result<Option<Cow<'_, JsonValue>>> {
Ok(match capability {
"m.change_password" => Some(Cow::Owned(to_json_value(&self.change_password)?)),
"m.room_versions" => Some(Cow::Owned(to_json_value(&self.room_versions)?)),
_ => self.custom_capabilities.get(capability).map(Cow::Borrowed),
})
}
/// Sets a capability to the given value.
pub fn set(&mut self, capability: &str, value: JsonValue) -> serde_json::Result<()> {
match capability {
"m.change_password" => self.change_password = from_json_value(value)?,
"m.room_versions" => self.room_versions = from_json_value(value)?,
_ => {
self.custom_capabilities.insert(capability.to_owned(), value);
}
}
Ok(())
}
}
/// Information about the m.change_password capability
#[derive(Clone, Debug, Serialize, Deserialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct ChangePasswordCapability {
/// `true` if the user can change their password, `false` otherwise.
pub enabled: bool,
}
impl ChangePasswordCapability {
/// Creates a new `ChangePasswordCapability` with the given enabled flag.
pub fn new(enabled: bool) -> Self {
Self { enabled }
}
/// Returns whether all fields have their default value.
pub fn is_default(&self) -> bool {
self.enabled
}
}
impl Default for ChangePasswordCapability {
fn default() -> Self {
Self { enabled: true }
}
}
/// Information about the m.room_versions capability
#[derive(Clone, Debug, Serialize, Deserialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct RoomVersionsCapability {
/// The default room version the server is using for new rooms.
pub default: RoomVersionId,
/// A detailed description of the room versions the server supports.
pub available: BTreeMap<RoomVersionId, RoomVersionStability>,
}
impl RoomVersionsCapability {
/// Creates a new `RoomVersionsCapability` with the given default room version ID and room
/// version descriptions.
pub fn new(
default: RoomVersionId,
available: BTreeMap<RoomVersionId, RoomVersionStability>,
) -> Self {
Self { default, available }
}
/// Returns whether all fields have their default value.
pub fn is_default(&self) -> bool {
self.default == RoomVersionId::Version1
&& self.available.len() == 1
&& self
.available
.get(&RoomVersionId::Version1)
.map(|stability| *stability == RoomVersionStability::Stable)
.unwrap_or(false)
}
}
impl Default for RoomVersionsCapability {
fn default() -> Self {
Self {
default: RoomVersionId::Version1,
available: btreemap! { RoomVersionId::Version1 => RoomVersionStability::Stable },
}
}
}
/// The stability of a room version
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
#[ruma_enum(rename_all = "lowercase")]
pub enum RoomVersionStability {
/// Support for the given version is stable.
Stable,
/// Support for the given version is unstable.
Unstable,
#[doc(hidden)]
_Custom(String),
}