#![allow(clippy::needless_lifetimes)]
#![cfg_attr(feature = "nightly", feature(proc_macro_span))]
extern crate proc_macro;
mod declare_derive;
mod dollar_macro;
mod lerp_derive;
mod part_state;
mod util;
use proc_macro::TokenStream;
use quote::quote;
use syn::{DeriveInput, parse_macro_input};
mod child_template;
mod fn_widget_macro;
mod pipe_macro;
mod rdl_macro;
mod simple_declare_attr;
mod watch_macro;
pub(crate) use rdl_macro::*;
pub(crate) mod declare_obj;
pub(crate) mod distinct_pipe_macro;
pub(crate) mod error;
pub(crate) mod symbol_process;
#[proc_macro_derive(SingleChild)]
pub fn single_child_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let name = input.ident;
quote! {
impl #impl_generics SingleChild for #name #ty_generics #where_clause {}
}
.into()
}
#[proc_macro_derive(MultiChild)]
pub fn multi_child_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let name = input.ident;
quote! {
impl #impl_generics MultiChild for #name #ty_generics #where_clause {}
}
.into()
}
#[proc_macro_derive(Lerp)]
pub fn lerp_derive(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
lerp_derive::lerp_derive(&mut input)
.unwrap_or_else(|e| e.into_compile_error())
.into()
}
#[proc_macro_derive(Declare, attributes(declare))]
pub fn declare_trait_macro_derive(input: TokenStream) -> TokenStream {
let mut stt = parse_macro_input!(input as syn::ItemStruct);
declare_derive::declare_derive(&mut stt)
.unwrap_or_else(|e| e.into_compile_error())
.into()
}
#[proc_macro_attribute]
pub fn simple_declare(attr: TokenStream, item: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(item as syn::ItemStruct);
let stateless = syn::parse::<syn::Ident>(attr).is_ok_and(|i| i == "stateless");
simple_declare_attr::simple_declarer_attr(&mut input, stateless)
.unwrap_or_else(|e| e.into_compile_error())
.into()
}
#[proc_macro_derive(Template, attributes(template))]
pub fn child_template_trait_derive(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
child_template::derive_child_template(&mut input)
.unwrap_or_else(|e| e.into_compile_error())
.into()
}
#[allow(clippy::doc_lazy_continuation)]
#[proc_macro]
pub fn rdl(input: TokenStream) -> TokenStream { RdlMacro::gen_code(input.into(), None).into() }
#[proc_macro]
pub fn fn_widget(input: TokenStream) -> TokenStream {
fn_widget_macro::gen_code(input.into(), None).into()
}
#[proc_macro]
pub fn ribir_expanded_ಠ_ಠ(input: TokenStream) -> TokenStream { input }
#[proc_macro]
pub fn pipe(input: TokenStream) -> TokenStream { pipe_macro::gen_code(input.into(), None).into() }
#[proc_macro]
pub fn distinct_pipe(input: TokenStream) -> TokenStream {
distinct_pipe_macro::gen_code(input.into(), None).into()
}
#[proc_macro]
pub fn watch(input: TokenStream) -> TokenStream { watch_macro::gen_code(input.into(), None).into() }
#[proc_macro]
pub fn part_writer(input: TokenStream) -> TokenStream {
part_state::gen_part_writer(input.into(), None).into()
}
#[proc_macro]
pub fn part_watcher(input: TokenStream) -> TokenStream {
part_state::gen_part_watcher(input.into(), None).into()
}
#[proc_macro]
pub fn part_reader(input: TokenStream) -> TokenStream {
part_state::gen_part_reader(input.into(), None).into()
}
#[proc_macro]
pub fn include_crate_svg(input: TokenStream) -> TokenStream {
let IncludeSvgArgs { path, inherit_fill, inherit_stroke } =
parse_macro_input! { input as IncludeSvgArgs };
let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let path = std::path::Path::new(&dir).join(path);
include_svg_from_path(path, inherit_fill, inherit_stroke)
}
#[cfg(feature = "nightly")]
#[proc_macro]
pub fn include_svg(input: TokenStream) -> TokenStream {
let IncludeSvgArgs { path, inherit_fill, inherit_stroke } =
parse_macro_input! { input as IncludeSvgArgs };
let mut span = proc_macro::Span::call_site();
while let Some(p) = span.parent() {
span = p;
}
let mut file = span.source_file().path();
file.pop();
file.push(path);
include_svg_from_path(file, inherit_fill, inherit_stroke)
}
fn include_svg_from_path(
path: std::path::PathBuf, inherit_fill: bool, inherit_stroke: bool,
) -> TokenStream {
let encoded_bytes = ribir_painter::Svg::open(path.as_path(), inherit_fill, inherit_stroke)
.and_then(|reader| reader.serialize());
match encoded_bytes {
Ok(data) => quote! {
Svg::deserialize(#data).unwrap()
}
.into(),
Err(err) => {
let err = format!("{err}({:?})", &path);
quote! { compile_error!(#err) }.into()
}
}
}
struct IncludeSvgArgs {
path: String,
inherit_fill: bool,
inherit_stroke: bool,
}
impl syn::parse::Parse for IncludeSvgArgs {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let path = input.parse::<syn::LitStr>()?.value();
input.parse::<syn::Token![,]>()?;
let inherit_fill = input.parse::<syn::LitBool>()?.value;
input.parse::<syn::Token![,]>()?;
let inherit_stroke = input.parse::<syn::LitBool>()?.value;
Ok(IncludeSvgArgs { path, inherit_fill, inherit_stroke })
}
}