Jonas Platte f6d419298c
Revert "api: Allow cfg attributes on rate_limited and authentication metadata fields"
cfg-dependent metadata is no longer needed.
This reverts commit 1c0dab5a479737bc2ae83ff710321c191dd502f7.
2022-02-13 12:13:50 +01:00

107 lines
3.6 KiB
Rust

//! Functions to aid the `Api::to_tokens` method.
use std::collections::BTreeSet;
use proc_macro2::{Ident, Span, TokenStream};
use proc_macro_crate::{crate_name, FoundCrate};
use quote::{format_ident, quote, ToTokens};
use syn::{parse_quote, visit::Visit, Attribute, Lifetime, NestedMeta, Type};
pub fn import_ruma_api() -> TokenStream {
if let Ok(FoundCrate::Name(name)) = crate_name("ruma-api") {
let import = format_ident!("{}", name);
quote! { ::#import }
} else if let Ok(FoundCrate::Name(name)) = crate_name("ruma") {
let import = format_ident!("{}", name);
quote! { ::#import::api }
} else if let Ok(FoundCrate::Name(name)) = crate_name("matrix-sdk") {
let import = format_ident!("{}", name);
quote! { ::#import::ruma::api }
} else if let Ok(FoundCrate::Name(name)) = crate_name("matrix-sdk-appservice") {
let import = format_ident!("{}", name);
quote! { ::#import::ruma::api }
} else {
quote! { ::ruma_api }
}
}
pub fn map_option_literal<T: ToTokens>(ver: &Option<T>) -> TokenStream {
match ver {
Some(v) => quote! { ::std::option::Option::Some(#v) },
None => quote! { ::std::option::Option::None },
}
}
pub fn is_valid_endpoint_path(string: &str) -> bool {
string.as_bytes().iter().all(|b| (0x21..=0x7E).contains(b))
}
pub fn collect_lifetime_idents(lifetimes: &mut BTreeSet<Lifetime>, ty: &Type) {
struct Visitor<'lt>(&'lt mut BTreeSet<Lifetime>);
impl<'ast> Visit<'ast> for Visitor<'_> {
fn visit_lifetime(&mut self, lt: &'ast Lifetime) {
self.0.insert(lt.clone());
}
}
Visitor(lifetimes).visit_type(ty)
}
pub fn all_cfgs_expr(cfgs: &[Attribute]) -> Option<TokenStream> {
let sub_cfgs: Vec<_> = cfgs.iter().filter_map(extract_cfg).collect();
(!sub_cfgs.is_empty()).then(|| quote! { all( #(#sub_cfgs),* ) })
}
pub fn all_cfgs(cfgs: &[Attribute]) -> Option<Attribute> {
let cfg_expr = all_cfgs_expr(cfgs)?;
Some(parse_quote! { #[cfg( #cfg_expr )] })
}
pub fn extract_cfg(attr: &Attribute) -> Option<NestedMeta> {
if !attr.path.is_ident("cfg") {
return None;
}
let meta = attr.parse_meta().expect("cfg attribute can be parsed to syn::Meta");
let mut list = match meta {
syn::Meta::List(l) => l,
_ => panic!("unexpected cfg syntax"),
};
assert!(list.path.is_ident("cfg"), "expected cfg attributes only");
assert_eq!(list.nested.len(), 1, "expected one item inside cfg()");
Some(list.nested.pop().unwrap().into_value())
}
pub fn path_format_args_call(
mut format_string: String,
percent_encoding: &TokenStream,
) -> TokenStream {
let mut format_args = Vec::new();
while let Some(start_of_segment) = format_string.find(':') {
// ':' should only ever appear at the start of a segment
assert_eq!(&format_string[start_of_segment - 1..start_of_segment], "/");
let end_of_segment = match format_string[start_of_segment..].find('/') {
Some(rel_pos) => start_of_segment + rel_pos,
None => format_string.len(),
};
let path_var =
Ident::new(&format_string[start_of_segment + 1..end_of_segment], Span::call_site());
format_args.push(quote! {
#percent_encoding::utf8_percent_encode(
&::std::string::ToString::to_string(&self.#path_var),
#percent_encoding::NON_ALPHANUMERIC,
)
});
format_string.replace_range(start_of_segment..end_of_segment, "{}");
}
quote! {
format_args!(#format_string, #(#format_args),*)
}
}