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::{parse_str, Ident, Path, PathArguments};
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 mut path: Path = parse_str(&path).expect("vaild function type name");
45 if let Some(name) = path.segments.last_mut() {
46 name.arguments = PathArguments::None
47 }
48
49 quote! { #path }
50 }
51}
52
53impl Default for FunctionRegistry {
54 fn default() -> Self {
55 let fns = HashMap::new();
56 let mut result = Self { fns };
57
58 result.register("NUMBER", fluent_static_function::builtins::number);
59
60 result
61 }
62}
63
64impl FunctionCallGenerator for FunctionRegistry {
65 fn generate(
66 &self,
67 function_name: &str,
68 positional_args: &Ident,
69 named_args: &Ident,
70 ) -> Option<TokenStream> {
71 if let Some(fn_ident) = self.fns.get(function_name) {
72 Some(quote! {
73 #fn_ident(&#positional_args, &#named_args)
74 })
75 } else {
76 None
77 }
78 }
79}