raug_macros/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3
4struct SplitOutputs {
5    output: syn::Expr,
6    count: syn::LitInt,
7}
8
9impl syn::parse::Parse for SplitOutputs {
10    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
11        let output = input.parse()?;
12        input.parse::<syn::Token![,]>()?;
13        let count = input.parse()?;
14        Ok(Self { output, count })
15    }
16}
17
18#[proc_macro]
19pub fn split_outputs(input: TokenStream) -> TokenStream {
20    let input = syn::parse_macro_input!(input as SplitOutputs);
21
22    let output = input.output;
23
24    let count = input.count.base10_parse().unwrap();
25
26    let mut idents = vec![];
27    for i in 0..count {
28        let ident = syn::Ident::new(&format!("out{}", i), proc_macro2::Span::call_site());
29        idents.push(ident);
30    }
31
32    let start = quote! {
33        let raug::processor::ProcessorOutputs {
34            output_spec,
35            outputs,
36            mode,
37        } = #output;
38
39        let [#(#idents),*] = outputs else {
40            panic!("Expected {} outputs, got {}", #count, outputs.len());
41        };
42    };
43
44    let mut chunks = vec![];
45
46    for (i, ident) in idents.iter().enumerate() {
47        let chunk = quote! {
48            raug::processor::ProcessorOutputs::new(
49                std::slice::from_ref(&output_spec[#i]),
50                std::slice::from_mut(#ident),
51                mode,
52            )
53        };
54        chunks.push(chunk);
55    }
56
57    let output = quote! {{
58        #start
59
60        (#(#chunks),*)
61    }};
62
63    output.into()
64}
65
66struct IterProcIoAs {
67    inputs: syn::Ident,
68    input_types: syn::punctuated::Punctuated<syn::Type, syn::Token![,]>,
69    outputs: syn::Ident,
70    output_types: syn::punctuated::Punctuated<syn::Type, syn::Token![,]>,
71}
72
73impl syn::parse::Parse for IterProcIoAs {
74    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
75        let inputs = input.parse()?;
76        input.parse::<syn::Token![as]>()?;
77        let input_types;
78        syn::bracketed!(input_types in input);
79        let input_types = input_types.parse_terminated(syn::Type::parse, syn::Token![,])?;
80        input.parse::<syn::Token![,]>()?;
81        let outputs = input.parse()?;
82        input.parse::<syn::Token![as]>()?;
83        let output_types;
84        syn::bracketed!(output_types in input);
85        let output_types = output_types.parse_terminated(syn::Type::parse, syn::Token![,])?;
86        Ok(Self {
87            inputs,
88            outputs,
89            input_types,
90            output_types,
91        })
92    }
93}
94
95#[proc_macro]
96pub fn iter_proc_io_as(input: TokenStream) -> TokenStream {
97    let input = syn::parse_macro_input!(input as IterProcIoAs);
98
99    let inputs = input.inputs;
100    let outputs = input.outputs;
101
102    let input_count = input.input_types.len();
103    let output_count = input.output_types.len();
104
105    let mut input_idents = vec![];
106    for i in 0..input_count {
107        let ident = syn::Ident::new(&format!("in{}", i), proc_macro2::Span::call_site());
108        input_idents.push(ident);
109    }
110
111    let mut output_idents = vec![];
112    for i in 0..output_count {
113        let ident = syn::Ident::new(&format!("out{}", i), proc_macro2::Span::call_site());
114        output_idents.push(ident);
115    }
116
117    let start = quote! {
118        let raug::processor::ProcessorInputs {
119            input_specs,
120            inputs,
121            mode,
122            sample_rate,
123            block_size,
124        } = #inputs;
125
126        let [#(#input_idents),*] = inputs else {
127            panic!("Expected {} inputs, got {}", #input_count, inputs.len());
128        };
129
130        let raug::processor::ProcessorOutputs {
131            output_spec,
132            outputs,
133            mode,
134        } = #outputs;
135
136        let [#(#output_idents),*] = outputs else {
137            panic!("Expected {} outputs, got {}", #output_count, outputs.len());
138        };
139    };
140
141    let mut chunks = vec![];
142
143    for (i, (input_ident, input_typ)) in input_idents
144        .iter()
145        .zip(input.input_types.iter())
146        .enumerate()
147    {
148        if let syn::Type::Path(path) = input_typ {
149            if path.path.get_ident().unwrap() == "Any" {
150                let chunk = quote! {
151                    raug::processor::ProcessorInputs::new(
152                        std::slice::from_ref(&input_specs[#i]),
153                        std::slice::from_ref(#input_ident),
154                        mode,
155                        sample_rate,
156                        block_size,
157                    ).iter_input(0)
158                };
159                chunks.push(chunk);
160                continue;
161            }
162        }
163        let chunk = quote! {
164            raug::processor::ProcessorInputs::new(
165                std::slice::from_ref(&input_specs[#i]),
166                std::slice::from_ref(#input_ident),
167                mode,
168                sample_rate,
169                block_size,
170            ).iter_input_as::<#input_typ>(0)?
171        };
172        chunks.push(chunk);
173    }
174
175    for (i, (output_ident, output_typ)) in output_idents
176        .iter()
177        .zip(input.output_types.iter())
178        .enumerate()
179    {
180        if let syn::Type::Path(path) = output_typ {
181            if path.path.get_ident().unwrap() == "Any" {
182                let chunk = quote! {
183                    raug::processor::ProcessorOutputs::new(
184                        std::slice::from_ref(&output_spec[#i]),
185                        std::slice::from_mut(#output_ident),
186                        mode,
187                    ).iter_output_mut(0)
188                };
189                chunks.push(chunk);
190                continue;
191            }
192        }
193        let chunk = quote! {
194            raug::processor::ProcessorOutputs::new(
195                std::slice::from_ref(&output_spec[#i]),
196                std::slice::from_mut(#output_ident),
197                mode,
198            ).iter_output_mut_as::<#output_typ>(0)?
199        };
200        chunks.push(chunk);
201    }
202
203    let output = quote! {{
204        #start
205
206        raug::__itertools::izip!(#(#chunks),*)
207    }};
208
209    output.into()
210}