leptos_macro/
slice.rs

1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use quote::{quote, ToTokens};
5use syn::{
6    parse::{Parse, ParseStream},
7    parse_macro_input,
8    punctuated::Punctuated,
9    Token,
10};
11
12struct SliceMacroInput {
13    root: syn::Ident,
14    path: Punctuated<syn::Member, Token![.]>,
15}
16
17impl Parse for SliceMacroInput {
18    fn parse(input: ParseStream) -> syn::Result<Self> {
19        let root: syn::Ident = input.parse()?;
20        input.parse::<Token![.]>()?;
21        // do not accept trailing punctuation
22        let path: Punctuated<syn::Member, Token![.]> =
23            Punctuated::parse_separated_nonempty(input)?;
24
25        if path.is_empty() {
26            return Err(input.error("expected identifier"));
27        }
28
29        if !input.is_empty() {
30            return Err(input.error("unexpected token"));
31        }
32
33        Ok(Self { root, path })
34    }
35}
36
37impl ToTokens for SliceMacroInput {
38    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
39        let root = &self.root;
40        let path = &self.path;
41
42        tokens.extend(quote! {
43            ::leptos::reactive::computed::create_slice(
44                #root,
45                |st: &_| st.#path.clone(),
46                |st: &mut _, n| st.#path = n
47            )
48        })
49    }
50}
51
52pub fn slice_impl(tokens: TokenStream) -> TokenStream {
53    let input = parse_macro_input!(tokens as SliceMacroInput);
54    input.into_token_stream().into()
55}