From ae4c9243cbe103a79d1f7762817048ff884ebda1 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Wed, 9 Feb 2022 12:02:58 +0100 Subject: [PATCH] api: Move Metadata and MatrixVersion into new metadata module --- crates/ruma-api/src/lib.rs | 164 ++------------------------------ crates/ruma-api/src/metadata.rs | 161 +++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 158 deletions(-) create mode 100644 crates/ruma-api/src/metadata.rs diff --git a/crates/ruma-api/src/lib.rs b/crates/ruma-api/src/lib.rs index 243b460f..2b77400f 100644 --- a/crates/ruma-api/src/lib.rs +++ b/crates/ruma-api/src/lib.rs @@ -18,14 +18,9 @@ #[cfg(not(all(feature = "client", feature = "server")))] compile_error!("ruma_api's Cargo features only exist as a workaround are not meant to be disabled"); -use std::{ - convert::{TryFrom, TryInto as _}, - error::Error as StdError, - fmt::{self, Display}, -}; +use std::{convert::TryInto as _, error::Error as StdError}; use bytes::BufMut; -use http::Method; use ruma_identifiers::UserId; /// Generates a `ruma_api::Endpoint` from a concise definition. @@ -214,7 +209,11 @@ pub mod exports { pub use serde_json; } -use error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError, UnknownVersionError}; +mod metadata; + +pub use metadata::{MatrixVersion, Metadata}; + +use error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError}; /// An enum to control whether an access token should be added to outgoing requests #[derive(Clone, Copy, Debug)] @@ -401,154 +400,3 @@ pub enum AuthScheme { /// Authentication is performed by setting the `access_token` query parameter. QueryOnlyAccessToken, } - -/// Metadata about an API endpoint. -#[derive(Clone, Debug)] -#[allow(clippy::exhaustive_structs)] -pub struct Metadata { - /// A human-readable description of the endpoint. - pub description: &'static str, - - /// The HTTP method used by this endpoint. - pub method: Method, - - /// A unique identifier for this endpoint. - pub name: &'static str, - - /// (DEPRECATED) - pub path: &'static str, - - /// The unstable path of this endpoint's URL, often `None`, used for developmental purposes. - pub unstable_path: Option<&'static str>, - - /// The pre-v1.1 version of this endpoint's URL, `None` for post-v1.1 endpoints, supplemental - /// to `stable_path`. - pub r0_path: Option<&'static str>, - - /// The path of this endpoint's URL, with variable names where path parameters should be filled - /// in during a request. - pub stable_path: Option<&'static str>, - - /// Whether or not this endpoint is rate limited by the server. - pub rate_limited: bool, - - /// What authentication scheme the server uses for this endpoint. - pub authentication: AuthScheme, - - /// The matrix version that this endpoint was added in. - /// - /// Is None when this endpoint is unstable/unreleased. - pub added: Option, - - /// The matrix version that deprecated this endpoint. - /// - /// Deprecation often precedes one matrix version before removal. - // TODO add once try_into_http_request has been altered; - // This will make `try_into_http_request` emit a warning, - // see the corresponding documentation for more information. - pub deprecated: Option, - - /// The matrix version that removed this endpoint. - // TODO add once try_into_http_request has been altered; - // This will make `try_into_http_request` emit an error, - // see the corresponding documentation for more information. - pub removed: Option, -} - -/// The Matrix versions Ruma currently understands to exist. -/// -/// Matrix, since fall 2021, has a quarterly release schedule, using a global `vX.Y` versioning -/// scheme. -/// -/// Every new minor version denotes stable support for endpoints in a *relatively* -/// backwards-compatible manner. -/// -/// Matrix has a deprecation policy, read more about it here: . -// TODO add the following once `EndpointPath` and added/deprecated/removed macros are in place; -// Ruma keeps track of when endpoints are added, deprecated, and removed. It'll automatically -// select the right endpoint stability variation to use depending on which Matrix version you pass -// it with [`EndpointPath`], see its respective documentation for more. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] -pub enum MatrixVersion { - /// Version 1.0 of the Matrix specification. - /// - /// Retroactively defined as . - V1_0, - - /// Version 1.1 of the Matrix specification, released in Q4 2021. - /// - /// See . - V1_1, - - /// Version 1.2 of the Matrix specification, released in Q1 2022. - /// - /// See . - V1_2, -} - -impl TryFrom<&str> for MatrixVersion { - type Error = UnknownVersionError; - - fn try_from(value: &str) -> Result { - use MatrixVersion::*; - - Ok(match value { - // FIXME: these are likely not entirely correct; https://github.com/ruma/ruma/issues/852 - "v1.0" | - // Additional definitions according to https://spec.matrix.org/v1.2/#legacy-versioning - "r0.5.0" | "r0.6.0" | "r0.6.1" => V1_0, - "v1.1" => V1_1, - "v1.2" => V1_2, - _ => return Err(UnknownVersionError), - }) - } -} - -impl MatrixVersion { - /// Checks whether a version is compatible with another. - /// - /// A is compatible with B as long as B is equal or less, so long as A and B have the same major - /// versions. - /// - /// For example, v1.2 is compatible with v1.1, as it is likely only some additions of endpoints - /// on top of v1.1, but v1.1 would not be compatible with v1.2, as v1.1 cannot represent all of - /// v1.2, in a manner similar to set theory. - /// - /// Warning: Matrix has a deprecation policy, and Matrix versioning is not as straight-forward - /// as this function makes it out to be. This function only exists to prune major version - /// differences, and versions too new for `self`. - /// - /// This (considering if major versions are the same) is equivalent to a `self >= other` check. - pub fn is_superset_of(self, other: Self) -> bool { - let (major_l, minor_l) = self.into_parts(); - let (major_r, minor_r) = other.into_parts(); - major_l == major_r && minor_l >= minor_r - } - - /// Decompose the Matrix version into its major and minor number. - pub fn into_parts(self) -> (u8, u8) { - match self { - MatrixVersion::V1_0 => (1, 0), - MatrixVersion::V1_1 => (1, 1), - MatrixVersion::V1_2 => (1, 2), - } - } - - /// Try to turn a pair of (major, minor) version components back into a `MatrixVersion`. - pub fn from_parts(major: u8, minor: u8) -> Result { - match (major, minor) { - (1, 0) => Ok(MatrixVersion::V1_0), - (1, 1) => Ok(MatrixVersion::V1_1), - (1, 2) => Ok(MatrixVersion::V1_2), - _ => Err(UnknownVersionError), - } - } -} - -impl Display for MatrixVersion { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let (major, minor) = self.into_parts(); - f.write_str(&format!("v{}.{}", major, minor)) - } -} diff --git a/crates/ruma-api/src/metadata.rs b/crates/ruma-api/src/metadata.rs new file mode 100644 index 00000000..424a6929 --- /dev/null +++ b/crates/ruma-api/src/metadata.rs @@ -0,0 +1,161 @@ +use std::{ + convert::TryFrom, + fmt::{self, Display}, +}; + +use http::Method; + +use crate::{error::UnknownVersionError, AuthScheme}; + +/// Metadata about an API endpoint. +#[derive(Clone, Debug)] +#[allow(clippy::exhaustive_structs)] +pub struct Metadata { + /// A human-readable description of the endpoint. + pub description: &'static str, + + /// The HTTP method used by this endpoint. + pub method: Method, + + /// A unique identifier for this endpoint. + pub name: &'static str, + + /// (DEPRECATED) + pub path: &'static str, + + /// The unstable path of this endpoint's URL, often `None`, used for developmental + /// purposes. + pub unstable_path: Option<&'static str>, + + /// The pre-v1.1 version of this endpoint's URL, `None` for post-v1.1 endpoints, + /// supplemental to `stable_path`. + pub r0_path: Option<&'static str>, + + /// The path of this endpoint's URL, with variable names where path parameters should be + /// filled in during a request. + pub stable_path: Option<&'static str>, + + /// Whether or not this endpoint is rate limited by the server. + pub rate_limited: bool, + + /// What authentication scheme the server uses for this endpoint. + pub authentication: AuthScheme, + + /// The matrix version that this endpoint was added in. + /// + /// Is None when this endpoint is unstable/unreleased. + pub added: Option, + + /// The matrix version that deprecated this endpoint. + /// + /// Deprecation often precedes one matrix version before removal. + // TODO add once try_into_http_request has been altered; + // This will make `try_into_http_request` emit a warning, + // see the corresponding documentation for more information. + pub deprecated: Option, + + /// The matrix version that removed this endpoint. + // TODO add once try_into_http_request has been altered; + // This will make `try_into_http_request` emit an error, + // see the corresponding documentation for more information. + pub removed: Option, +} + +/// The Matrix versions Ruma currently understands to exist. +/// +/// Matrix, since fall 2021, has a quarterly release schedule, using a global `vX.Y` versioning +/// scheme. +/// +/// Every new minor version denotes stable support for endpoints in a *relatively* +/// backwards-compatible manner. +/// +/// Matrix has a deprecation policy, read more about it here: . +// TODO add the following once `EndpointPath` and added/deprecated/removed macros are in place; +// Ruma keeps track of when endpoints are added, deprecated, and removed. It'll automatically +// select the right endpoint stability variation to use depending on which Matrix version you +// pass it with [`EndpointPath`], see its respective documentation for more. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] +pub enum MatrixVersion { + /// Version 1.0 of the Matrix specification. + /// + /// Retroactively defined as . + V1_0, + + /// Version 1.1 of the Matrix specification, released in Q4 2021. + /// + /// See . + V1_1, + + /// Version 1.2 of the Matrix specification, released in Q1 2022. + /// + /// See . + V1_2, +} + +impl TryFrom<&str> for MatrixVersion { + type Error = UnknownVersionError; + + fn try_from(value: &str) -> Result { + use MatrixVersion::*; + + Ok(match value { + // FIXME: these are likely not entirely correct; https://github.com/ruma/ruma/issues/852 + "v1.0" | + // Additional definitions according to https://spec.matrix.org/v1.2/#legacy-versioning + "r0.5.0" | "r0.6.0" | "r0.6.1" => V1_0, + "v1.1" => V1_1, + "v1.2" => V1_2, + _ => return Err(UnknownVersionError), + }) + } +} + +impl MatrixVersion { + /// Checks whether a version is compatible with another. + /// + /// A is compatible with B as long as B is equal or less, so long as A and B have the same + /// major versions. + /// + /// For example, v1.2 is compatible with v1.1, as it is likely only some additions of + /// endpoints on top of v1.1, but v1.1 would not be compatible with v1.2, as v1.1 + /// cannot represent all of v1.2, in a manner similar to set theory. + /// + /// Warning: Matrix has a deprecation policy, and Matrix versioning is not as + /// straight-forward as this function makes it out to be. This function only exists + /// to prune major version differences, and versions too new for `self`. + /// + /// This (considering if major versions are the same) is equivalent to a `self >= other` + /// check. + pub fn is_superset_of(self, other: Self) -> bool { + let (major_l, minor_l) = self.into_parts(); + let (major_r, minor_r) = other.into_parts(); + major_l == major_r && minor_l >= minor_r + } + + /// Decompose the Matrix version into its major and minor number. + pub fn into_parts(self) -> (u8, u8) { + match self { + MatrixVersion::V1_0 => (1, 0), + MatrixVersion::V1_1 => (1, 1), + MatrixVersion::V1_2 => (1, 2), + } + } + + /// Try to turn a pair of (major, minor) version components back into a `MatrixVersion`. + pub fn from_parts(major: u8, minor: u8) -> Result { + match (major, minor) { + (1, 0) => Ok(MatrixVersion::V1_0), + (1, 1) => Ok(MatrixVersion::V1_1), + (1, 2) => Ok(MatrixVersion::V1_2), + _ => Err(UnknownVersionError), + } + } +} + +impl Display for MatrixVersion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let (major, minor) = self.into_parts(); + f.write_str(&format!("v{}.{}", major, minor)) + } +}