fluent_static_codegen/
function.rs1use std::collections::HashMap;
2
3use fluent_static_function::FluentFunctionDescriptor;
4use proc_macro2::TokenStream;
5use quote::{format_ident, quote};
6use syn::Ident;
7
8pub trait FunctionCallGenerator {
9 fn generate(
10 &self,
11 function_name: &str,
12 positional_args: &Ident,
13 named_args: &Ident,
14 ) -> Option<TokenStream>;
15}
16
17pub struct FunctionRegistry {
18 fns: HashMap<String, TokenStream>,
19}
20
21impl FunctionRegistry {
22 pub fn register(
23 &mut self,
24 function_id: &str,
25 function_descriptor: impl FluentFunctionDescriptor,
26 ) -> &Self {
27 self.fns
28 .insert(function_id.to_string(), Self::fqn(function_descriptor));
29 self
30 }
31
32 fn fqn(function_descriptor: impl FluentFunctionDescriptor) -> TokenStream {
33 let path = function_descriptor.type_name();
34
35 let path = if path.starts_with("fluent_static_function::builtins") {
39 path.replace("fluent_static_function", "fluent_static::function")
40 } else {
41 path.to_string()
42 };
43
44 let parts: Vec<&str> = path.split("::").collect();
45 let idents: Vec<_> = parts.iter().map(|part| format_ident!("{}", part)).collect();
46
47 quote! { #(#idents)::* }
48 }
49}
50
51impl Default for FunctionRegistry {
52 fn default() -> Self {
53 let fns = HashMap::new();
54 let mut result = Self { fns };
55
56 result.register("NUMBER", fluent_static_function::builtins::number);
57
58 result
59 }
60}
61
62impl FunctionCallGenerator for FunctionRegistry {
63 fn generate(
64 &self,
65 function_name: &str,
66 positional_args: &Ident,
67 named_args: &Ident,
68 ) -> Option<TokenStream> {
69 if let Some(fn_ident) = self.fns.get(function_name) {
70 Some(quote! {
71 #fn_ident(&#positional_args, &#named_args)
72 })
73 } else {
74 None
75 }
76 }
77}