Move documentation of ruma_api! from ruma-api-macros to ruma-api
This commit is contained in:
parent
f2addacccb
commit
0f803e2acf
@ -3,11 +3,7 @@
|
||||
//!
|
||||
//! See the documentation for the `ruma_api!` macro for usage details.
|
||||
|
||||
#![deny(
|
||||
missing_copy_implementations,
|
||||
missing_debug_implementations,
|
||||
// missing_docs, # Uncomment when https://github.com/rust-lang/rust/pull/60562 is released.
|
||||
)]
|
||||
#![deny(missing_copy_implementations, missing_debug_implementations)]
|
||||
#![allow(clippy::cognitive_complexity)]
|
||||
// Since we support Rust 1.36.0, we can't apply this suggestion yet
|
||||
#![allow(clippy::use_self)]
|
||||
@ -24,175 +20,6 @@ use crate::api::{Api, RawApi};
|
||||
|
||||
mod api;
|
||||
|
||||
/// Generates a `ruma_api::Endpoint` from a concise definition.
|
||||
///
|
||||
/// The macro expects the following structure as input:
|
||||
///
|
||||
/// ```ignore
|
||||
/// ruma_api! {
|
||||
/// metadata {
|
||||
/// description: &'static str
|
||||
/// method: http::Method,
|
||||
/// name: &'static str,
|
||||
/// path: &'static str,
|
||||
/// rate_limited: bool,
|
||||
/// requires_authentication: bool,
|
||||
/// }
|
||||
///
|
||||
/// request {
|
||||
/// // Struct fields for each piece of data required
|
||||
/// // to make a request to this API endpoint.
|
||||
/// }
|
||||
///
|
||||
/// response {
|
||||
/// // Struct fields for each piece of data expected
|
||||
/// // in the response from this API endpoint.
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This will generate a `ruma_api::Metadata` value to be used for the `ruma_api::Endpoint`'s
|
||||
/// associated constant, single `Request` and `Response` structs, and the necessary trait
|
||||
/// implementations to convert the request into a `http::Request` and to create a response from a
|
||||
/// `http::Response` and vice versa.
|
||||
///
|
||||
/// The details of each of the three sections of the macros are documented below.
|
||||
///
|
||||
/// ## Metadata
|
||||
///
|
||||
/// * `description`: A short description of what the endpoint does.
|
||||
/// * `method`: The HTTP method used for requests to the endpoint.
|
||||
/// It's not necessary to import `http::Method`'s associated constants. Just write
|
||||
/// the value as if it was imported, e.g. `GET`.
|
||||
/// * `name`: A unique name for the endpoint.
|
||||
/// Generally this will be the same as the containing module.
|
||||
/// * `path`: The path component of the URL for the endpoint, e.g. "/foo/bar".
|
||||
/// Components of the path that are parameterized can indicate a varible by using a Rust
|
||||
/// identifier prefixed with a colon, e.g. `/foo/:some_parameter`.
|
||||
/// A corresponding query string parameter will be expected in the request struct (see below
|
||||
/// for details).
|
||||
/// * `rate_limited`: Whether or not the endpoint enforces rate limiting on requests.
|
||||
/// * `requires_authentication`: Whether or not the endpoint requires a valid access token.
|
||||
///
|
||||
/// ## Request
|
||||
///
|
||||
/// The request block contains normal struct field definitions.
|
||||
/// Doc comments and attributes are allowed as normal.
|
||||
/// There are also a few special attributes available to control how the struct is converted into a
|
||||
/// `http::Request`:
|
||||
///
|
||||
/// * `#[ruma_api(header = HEADER_NAME)]`: Fields with this attribute will be treated as HTTP
|
||||
/// headers on the request.
|
||||
/// The value must implement `AsRef<str>`.
|
||||
/// Generally this is a `String`.
|
||||
/// The attribute value shown above as `HEADER_NAME` must be a header name constant from
|
||||
/// `http::header`, e.g. `CONTENT_TYPE`.
|
||||
/// * `#[ruma_api(path)]`: Fields with this attribute will be inserted into the matching path
|
||||
/// component of the request URL.
|
||||
/// * `#[ruma_api(query)]`: Fields with this attribute will be inserting into the URL's query
|
||||
/// string.
|
||||
/// * `#[ruma_api(query_map)]`: Instead of individual query fields, one query_map field, of any
|
||||
/// type that implements `IntoIterator<Item = (String, String)>` (e.g.
|
||||
/// `HashMap<String, String>`, can be used for cases where an endpoint supports arbitrary query
|
||||
/// parameters.
|
||||
///
|
||||
/// Any field that does not include one of these attributes will be part of the request's JSON
|
||||
/// body.
|
||||
///
|
||||
/// ## Response
|
||||
///
|
||||
/// Like the request block, the response block consists of normal struct field definitions.
|
||||
/// Doc comments and attributes are allowed as normal.
|
||||
/// There is also a special attribute available to control how the struct is created from a
|
||||
/// `http::Request`:
|
||||
///
|
||||
/// * `#[ruma_api(header = HEADER_NAME)]`: Fields with this attribute will be treated as HTTP
|
||||
/// headers on the response.
|
||||
/// The value must implement `AsRef<str>`.
|
||||
/// Generally this is a `String`.
|
||||
/// The attribute value shown above as `HEADER_NAME` must be a header name constant from
|
||||
/// `http::header`, e.g. `CONTENT_TYPE`.
|
||||
///
|
||||
/// Any field that does not include the above attribute will be expected in the response's JSON
|
||||
/// body.
|
||||
///
|
||||
/// ## Newtype bodies
|
||||
///
|
||||
/// Both the request and response block also support "newtype bodies" by using the
|
||||
/// `#[ruma_api(body)]` attribute on a field. If present on a field, the entire request or response
|
||||
/// body will be treated as the value of the field. This allows you to treat the entire request or
|
||||
/// response body as a specific type, rather than a JSON object with named fields. Only one field in
|
||||
/// each struct can be marked with this attribute. It is an error to have a newtype body field and
|
||||
/// normal body fields within the same struct.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// pub mod some_endpoint {
|
||||
/// use ruma_api_macros::ruma_api;
|
||||
///
|
||||
/// ruma_api! {
|
||||
/// metadata {
|
||||
/// description: "Does something.",
|
||||
/// method: GET,
|
||||
/// name: "some_endpoint",
|
||||
/// path: "/_matrix/some/endpoint/:baz",
|
||||
/// rate_limited: false,
|
||||
/// requires_authentication: false,
|
||||
/// }
|
||||
///
|
||||
/// request {
|
||||
/// pub foo: String,
|
||||
///
|
||||
/// #[ruma_api(header = CONTENT_TYPE)]
|
||||
/// pub content_type: String,
|
||||
///
|
||||
/// #[ruma_api(query)]
|
||||
/// pub bar: String,
|
||||
///
|
||||
/// #[ruma_api(path)]
|
||||
/// pub baz: String,
|
||||
/// }
|
||||
///
|
||||
/// response {
|
||||
/// #[ruma_api(header = CONTENT_TYPE)]
|
||||
/// pub content_type: String,
|
||||
///
|
||||
/// pub value: String,
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// pub mod newtype_body_endpoint {
|
||||
/// use ruma_api_macros::ruma_api;
|
||||
///
|
||||
/// #[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
/// pub struct MyCustomType {
|
||||
/// pub foo: String,
|
||||
/// }
|
||||
///
|
||||
/// ruma_api! {
|
||||
/// metadata {
|
||||
/// description: "Does something.",
|
||||
/// method: GET,
|
||||
/// name: "newtype_body_endpoint",
|
||||
/// path: "/_matrix/some/newtype/body/endpoint",
|
||||
/// rate_limited: false,
|
||||
/// requires_authentication: false,
|
||||
/// }
|
||||
///
|
||||
/// request {
|
||||
/// #[ruma_api(body)]
|
||||
/// pub file: Vec<u8>,
|
||||
/// }
|
||||
///
|
||||
/// response {
|
||||
/// #[ruma_api(body)]
|
||||
/// pub my_custom_type: MyCustomType,
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[proc_macro]
|
||||
pub fn ruma_api(input: TokenStream) -> TokenStream {
|
||||
let raw_api = syn::parse_macro_input!(input as RawApi);
|
||||
|
170
src/lib.rs
170
src/lib.rs
@ -27,6 +27,176 @@ use ruma_identifiers;
|
||||
use serde_json;
|
||||
use serde_urlencoded;
|
||||
|
||||
/// Generates a `ruma_api::Endpoint` from a concise definition.
|
||||
///
|
||||
/// The macro expects the following structure as input:
|
||||
///
|
||||
/// ```text
|
||||
/// ruma_api! {
|
||||
/// metadata {
|
||||
/// description: &'static str,
|
||||
/// method: http::Method,
|
||||
/// name: &'static str,
|
||||
/// path: &'static str,
|
||||
/// rate_limited: bool,
|
||||
/// requires_authentication: bool,
|
||||
/// }
|
||||
///
|
||||
/// request {
|
||||
/// // Struct fields for each piece of data required
|
||||
/// // to make a request to this API endpoint.
|
||||
/// }
|
||||
///
|
||||
/// response {
|
||||
/// // Struct fields for each piece of data expected
|
||||
/// // in the response from this API endpoint.
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This will generate a `ruma_api::Metadata` value to be used for the `ruma_api::Endpoint`'s
|
||||
/// associated constant, single `Request` and `Response` structs, and the necessary trait
|
||||
/// implementations to convert the request into a `http::Request` and to create a response from a
|
||||
/// `http::Response` and vice versa.
|
||||
///
|
||||
/// The details of each of the three sections of the macros are documented below.
|
||||
///
|
||||
/// ## Metadata
|
||||
///
|
||||
/// * `description`: A short description of what the endpoint does.
|
||||
/// * `method`: The HTTP method used for requests to the endpoint.
|
||||
/// It's not necessary to import `http::Method`'s associated constants. Just write
|
||||
/// the value as if it was imported, e.g. `GET`.
|
||||
/// * `name`: A unique name for the endpoint.
|
||||
/// Generally this will be the same as the containing module.
|
||||
/// * `path`: The path component of the URL for the endpoint, e.g. "/foo/bar".
|
||||
/// Components of the path that are parameterized can indicate a varible by using a Rust
|
||||
/// identifier prefixed with a colon, e.g. `/foo/:some_parameter`.
|
||||
/// A corresponding query string parameter will be expected in the request struct (see below
|
||||
/// for details).
|
||||
/// * `rate_limited`: Whether or not the endpoint enforces rate limiting on requests.
|
||||
/// * `requires_authentication`: Whether or not the endpoint requires a valid access token.
|
||||
///
|
||||
/// ## Request
|
||||
///
|
||||
/// The request block contains normal struct field definitions.
|
||||
/// Doc comments and attributes are allowed as normal.
|
||||
/// There are also a few special attributes available to control how the struct is converted into a
|
||||
/// `http::Request`:
|
||||
///
|
||||
/// * `#[ruma_api(header = HEADER_NAME)]`: Fields with this attribute will be treated as HTTP
|
||||
/// headers on the request.
|
||||
/// The value must implement `AsRef<str>`.
|
||||
/// Generally this is a `String`.
|
||||
/// The attribute value shown above as `HEADER_NAME` must be a header name constant from
|
||||
/// `http::header`, e.g. `CONTENT_TYPE`.
|
||||
/// * `#[ruma_api(path)]`: Fields with this attribute will be inserted into the matching path
|
||||
/// component of the request URL.
|
||||
/// * `#[ruma_api(query)]`: Fields with this attribute will be inserting into the URL's query
|
||||
/// string.
|
||||
/// * `#[ruma_api(query_map)]`: Instead of individual query fields, one query_map field, of any
|
||||
/// type that implements `IntoIterator<Item = (String, String)>` (e.g.
|
||||
/// `HashMap<String, String>`, can be used for cases where an endpoint supports arbitrary query
|
||||
/// parameters.
|
||||
///
|
||||
/// Any field that does not include one of these attributes will be part of the request's JSON
|
||||
/// body.
|
||||
///
|
||||
/// ## Response
|
||||
///
|
||||
/// Like the request block, the response block consists of normal struct field definitions.
|
||||
/// Doc comments and attributes are allowed as normal.
|
||||
/// There is also a special attribute available to control how the struct is created from a
|
||||
/// `http::Request`:
|
||||
///
|
||||
/// * `#[ruma_api(header = HEADER_NAME)]`: Fields with this attribute will be treated as HTTP
|
||||
/// headers on the response.
|
||||
/// The value must implement `AsRef<str>`.
|
||||
/// Generally this is a `String`.
|
||||
/// The attribute value shown above as `HEADER_NAME` must be a header name constant from
|
||||
/// `http::header`, e.g. `CONTENT_TYPE`.
|
||||
///
|
||||
/// Any field that does not include the above attribute will be expected in the response's JSON
|
||||
/// body.
|
||||
///
|
||||
/// ## Newtype bodies
|
||||
///
|
||||
/// Both the request and response block also support "newtype bodies" by using the
|
||||
/// `#[ruma_api(body)]` attribute on a field. If present on a field, the entire request or response
|
||||
/// body will be treated as the value of the field. This allows you to treat the entire request or
|
||||
/// response body as a specific type, rather than a JSON object with named fields. Only one field in
|
||||
/// each struct can be marked with this attribute. It is an error to have a newtype body field and
|
||||
/// normal body fields within the same struct.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// pub mod some_endpoint {
|
||||
/// use ruma_api_macros::ruma_api;
|
||||
///
|
||||
/// ruma_api! {
|
||||
/// metadata {
|
||||
/// description: "Does something.",
|
||||
/// method: POST,
|
||||
/// name: "some_endpoint",
|
||||
/// path: "/_matrix/some/endpoint/:baz",
|
||||
/// rate_limited: false,
|
||||
/// requires_authentication: false,
|
||||
/// }
|
||||
///
|
||||
/// request {
|
||||
/// pub foo: String,
|
||||
///
|
||||
/// #[ruma_api(header = CONTENT_TYPE)]
|
||||
/// pub content_type: String,
|
||||
///
|
||||
/// #[ruma_api(query)]
|
||||
/// pub bar: String,
|
||||
///
|
||||
/// #[ruma_api(path)]
|
||||
/// pub baz: String,
|
||||
/// }
|
||||
///
|
||||
/// response {
|
||||
/// #[ruma_api(header = CONTENT_TYPE)]
|
||||
/// pub content_type: String,
|
||||
///
|
||||
/// pub value: String,
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// pub mod newtype_body_endpoint {
|
||||
/// use ruma_api_macros::ruma_api;
|
||||
/// use serde::{Deserialize, Serialize};
|
||||
///
|
||||
/// #[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
/// pub struct MyCustomType {
|
||||
/// pub foo: String,
|
||||
/// }
|
||||
///
|
||||
/// ruma_api! {
|
||||
/// metadata {
|
||||
/// description: "Does something.",
|
||||
/// method: PUT,
|
||||
/// name: "newtype_body_endpoint",
|
||||
/// path: "/_matrix/some/newtype/body/endpoint",
|
||||
/// rate_limited: false,
|
||||
/// requires_authentication: false,
|
||||
/// }
|
||||
///
|
||||
/// request {
|
||||
/// #[ruma_api(body)]
|
||||
/// pub file: Vec<u8>,
|
||||
/// }
|
||||
///
|
||||
/// response {
|
||||
/// #[ruma_api(body)]
|
||||
/// pub my_custom_type: MyCustomType,
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(feature = "with-ruma-api-macros")]
|
||||
pub use ruma_api_macros::ruma_api;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user