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 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}