diff --git a/Cargo.lock b/Cargo.lock index bd883610..a1f62e04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,12 +47,56 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + [[package]] name = "anstyle" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + [[package]] name = "anyhow" version = "1.0.86" @@ -442,7 +486,7 @@ dependencies = [ "js-sys", "num-traits", "wasm-bindgen", - "windows-link", + "windows-link 0.1.1", ] [[package]] @@ -463,7 +507,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" dependencies = [ "clap_builder", - "clap_derive", ] [[package]] @@ -472,20 +515,10 @@ version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" dependencies = [ + "anstream", "anstyle", "clap_lex", -] - -[[package]] -name = "clap_derive" -version = "4.5.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn", + "strsim", ] [[package]] @@ -509,6 +542,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + [[package]] name = "conduit" version = "0.11.0-alpha" @@ -814,7 +853,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2", "quote", "syn", @@ -1140,12 +1179,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - [[package]] name = "hermit-abi" version = "0.3.9" @@ -1579,6 +1612,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + [[package]] name = "itertools" version = "0.12.1" @@ -2015,6 +2054,12 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "openssl-probe" version = "0.1.5" @@ -3245,6 +3290,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subslice" version = "0.2.3" @@ -3824,6 +3875,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "1.8.0" @@ -4048,7 +4105,7 @@ checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" dependencies = [ "windows-implement 0.60.0", "windows-interface 0.59.1", - "windows-link", + "windows-link 0.1.1", "windows-result 0.3.2", "windows-strings 0.4.0", ] @@ -4103,6 +4160,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-result" version = "0.2.0" @@ -4118,7 +4181,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" dependencies = [ - "windows-link", + "windows-link 0.1.1", ] [[package]] @@ -4137,7 +4200,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" dependencies = [ - "windows-link", + "windows-link 0.1.1", ] [[package]] @@ -4167,6 +4230,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -4344,6 +4416,12 @@ checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "xtask" version = "0.11.0-alpha" +dependencies = [ + "clap", + "conduit-config", + "serde", + "serde_json", +] [[package]] name = "yansi" diff --git a/Cargo.toml b/Cargo.toml index d44e4272..0a3563ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,12 +21,14 @@ rust-version = "1.88.0" [workspace.dependencies] bytesize = "2" +clap = "4" conduit-config.path = "conduit-config" conduit-macros.path = "conduit-macros" reqwest = { version = "0.12", default-features = false } ruma.git = "https://github.com/ruma/ruma.git" rusty-s3 = "0.8" serde = "1" +serde_json = "1" thiserror = "2" [profile.dev] diff --git a/conduit-config/src/rate_limiting.rs b/conduit-config/src/rate_limiting.rs index 991301e0..4db857c0 100644 --- a/conduit-config/src/rate_limiting.rs +++ b/conduit-config/src/rate_limiting.rs @@ -197,11 +197,14 @@ pub trait DocumentRestrictions: Sized { #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd)] #[cfg_attr( feature = "doc-generators", - derive(conduit_macros::DocumentRestrictions) + derive(conduit_macros::DocumentRestrictions, serde::Serialize) )] #[serde(rename_all = "snake_case")] pub enum ClientRestriction { + /// Endpoint for registering a new user account. May be called multiples times for a single + /// registration if there are extra steps, e.g. providing a registration token. Registration, + /// Endpoint used for logging into an existing account. Login, RegistrationTokenValidity, @@ -221,7 +224,7 @@ pub enum ClientRestriction { #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd)] #[cfg_attr( feature = "doc-generators", - derive(conduit_macros::DocumentRestrictions) + derive(conduit_macros::DocumentRestrictions, serde::Serialize) )] #[serde(rename_all = "snake_case")] pub enum FederationRestriction { diff --git a/conduit-macros/Cargo.toml b/conduit-macros/Cargo.toml index 69aec5e0..969fad4e 100644 --- a/conduit-macros/Cargo.toml +++ b/conduit-macros/Cargo.toml @@ -10,6 +10,7 @@ version = "0.11.0-alpha" proc-macro = true [dependencies] +# Parsing and quoting tokens proc-macro2 = "1" quote = "1" syn = { version = "2", features = ["full"] } diff --git a/conduit-macros/src/doc_generators.rs b/conduit-macros/src/doc_generators.rs index befc0e19..2f06762f 100644 --- a/conduit-macros/src/doc_generators.rs +++ b/conduit-macros/src/doc_generators.rs @@ -1,16 +1,13 @@ -use std::{fmt::Display, path::Path}; - -use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; use quote::{ToTokens, quote}; -use syn::{Attribute, Expr, Field, Ident, ItemEnum, Lit, MetaNameValue, Variant, parse::Parse}; +use syn::{Expr, Ident, ItemEnum, Lit, MetaNameValue, Variant, parse::Parse}; -pub struct Restrictions { +pub(super) struct Restrictions { ident: Ident, variants: Vec, } -pub struct Restriction { +struct Restriction { ident: Ident, doc_comments: Vec, } @@ -62,7 +59,7 @@ impl ToTokens for Restrictions { let output = quote! { impl DocumentRestrictions for #ident { fn variant_doc_comments() -> Vec<(Self, String)> { - vec![#( (#variants), )*] + vec![#((#variants)),*] } } }; diff --git a/conduit-macros/src/lib.rs b/conduit-macros/src/lib.rs index 64777d44..603ed46f 100644 --- a/conduit-macros/src/lib.rs +++ b/conduit-macros/src/lib.rs @@ -4,6 +4,7 @@ use quote::quote; #[cfg(feature = "doc-generators")] mod doc_generators; +/// Allows for the doc comments of restrictions to be accessed at runtime. #[cfg(feature = "doc-generators")] #[proc_macro_derive(DocumentRestrictions)] pub fn document_restrictions(item: TokenStream) -> TokenStream { diff --git a/conduit/Cargo.toml b/conduit/Cargo.toml index e4bc58f1..91e0cd94 100644 --- a/conduit/Cargo.toml +++ b/conduit/Cargo.toml @@ -47,7 +47,7 @@ tokio = { version = "1", features = ["fs", "macros", "signal", "sync"] } bytes = "1" http = "1" # Used for ruma wrapper -serde_json = { version = "1", features = ["raw_value"] } +serde_json = { workspace = true, features = ["raw_value"] } # Used for appservice registration files serde_yaml = "0.9" # Used for pdu definition @@ -116,14 +116,7 @@ hmac = "0.12" sha-1 = "0.10" # used for conduit's CLI and admin room command parsing chrono = "0.4" -clap = { version = "4", default-features = false, features = [ - "derive", - "error-context", - "help", - "std", - "string", - "usage", -] } +clap.workspace = true humantime = "2" shell-words = "1.1.0" diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 1fd9661d..ed931538 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -7,6 +7,12 @@ rust-version.workspace = true version = "0.11.0-alpha" [dependencies] +# Processing commands +clap.workspace = true +# Documentation generation for the configuration +conduit-config = { workspace = true, features = ["doc-generators"] } +serde.workspace = true +serde_json.workspace = true [lints] workspace = true diff --git a/xtask/src/generate_docs.rs b/xtask/src/generate_docs.rs new file mode 100644 index 00000000..0483ced6 --- /dev/null +++ b/xtask/src/generate_docs.rs @@ -0,0 +1,49 @@ +use std::{ + fs::{File, create_dir_all}, + io::Write, +}; + +use conduit_config::rate_limiting::{ + ClientRestriction, DocumentRestrictions, FederationRestriction, +}; + +pub fn run() { + let mut markdown_text = String::new(); + + markdown_text.push_str("\n"); + for (restriction, comment) in ClientRestriction::variant_doc_comments() { + markdown_text.push_str(&format!( + "##### {}\n{}\n", + restriction_to_string(&restriction), + comment + )); + } + markdown_text.push_str("\n"); + + markdown_text.push_str("\n"); + for (restriction, comment) in FederationRestriction::variant_doc_comments() { + markdown_text.push_str(&format!( + "##### `{}`\n{}\n", + restriction_to_string(&restriction), + comment + )); + } + markdown_text.push_str("\n"); + + create_dir_all("./target/docs").unwrap(); + let mut file = File::create("./target/docs/rate-limiting.md").unwrap(); + + file.write_all(markdown_text.as_bytes()).unwrap(); +} + +fn restriction_to_string(restriction: &T) -> String { + // Maybe there is a better way to convert it to snake_case without extra dependencies added + // to Cargo.lock + serde_json::to_string(restriction) + .expect("Unit variants can always serialize") + .strip_prefix("\"") + .expect("serde_json always adds this prefix") + .strip_suffix("\"") + .expect("serde_json always adds this suffix") + .to_owned() +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index e7a11a96..5fc843b6 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,3 +1,20 @@ +mod generate_docs; + +use clap::{Parser, Subcommand}; + +#[derive(Parser)] +struct Xtask { + #[clap(subcommand)] + cmd: Command, +} + +#[derive(Subcommand)] +enum Command { + GenerateDocs, +} + fn main() { - println!("Hello, world!"); + match Xtask::parse().cmd { + Command::GenerateDocs => generate_docs::run(), + } }