1use crate::{structs, Error};
2use handlebars::{handlebars_helper, Handlebars};
3use structs::{InstructionType, TemplateHelper, IDL};
4
5pub(crate) fn create_handlebars_registry() -> Handlebars<'static> {
6 handlebars_helper!(snakecase: |name: String| name.chars().enumerate().fold(
7 "".to_string(),
8 |acc, (index, letter)| {
9 if letter.is_uppercase() {
10 if index == 0 {
11 format!("{}{}", acc, letter.to_lowercase())
12 } else {
13 format!("{}_{}", acc, letter.to_lowercase())
14 }
15 } else {
16 format!("{}{}", acc, letter)
17 }
18 }
19 )
20 );
21
22 handlebars_helper!(pascalcase: |name: String|{
23 let mut passcalcase_chars: Vec<char> = name.chars().collect();
24 if passcalcase_chars.is_empty() {
25 "".to_string()
26 } else {
27 let first: Vec<char> = passcalcase_chars[0].to_uppercase().to_string().chars().collect();
28 passcalcase_chars[0] = *first.first().unwrap_or(&' ');
29 let passcalcase: String = passcalcase_chars.into_iter().collect();
30 passcalcase
31 }
32 }
33 );
34
35 handlebars_helper!(type_from_account_field: |account_field_type: InstructionType| type_from_account_field_impl(account_field_type));
36
37 handlebars_helper!(debug_idl: |idl: IDL|serde_json::to_string(&idl).unwrap_or("".to_string()));
38
39 let mut handlebars = Handlebars::new();
40
41 handlebars.register_helper("snakecase", Box::new(snakecase));
42 handlebars.register_helper("pascalcase", Box::new(pascalcase));
43 handlebars.register_helper("type_from_account_field", Box::new(type_from_account_field));
44 handlebars.register_helper("debug_idl", Box::new(debug_idl));
45 handlebars
46}
47
48pub fn apply_user_helpers(
49 helpers: Vec<TemplateHelper>,
50 handlebars: &mut handlebars::Handlebars,
51) -> Result<(), Error> {
52 for TemplateHelper {
53 helper_name,
54 script,
55 } in helpers
56 {
57 match handlebars.register_script_helper(&helper_name, &script) {
58 Ok(_) => {}
59 Err(err) => {
60 return Err(Error::CustomError {
61 message: format!("Error registering helper: {}", err),
62 })
63 }
64 }
65 }
66 Ok(())
67}
68
69fn type_from_account_field_impl(account_field_type: InstructionType) -> String {
70 match account_field_type {
71 InstructionType::String => "String".to_string(),
72 InstructionType::U8 => "u8".to_string(),
73 InstructionType::U16 => "u16".to_string(),
74 InstructionType::U32 => "u32".to_string(),
75 InstructionType::U64 => "u64".to_string(),
76 InstructionType::U128 => "u128".to_string(),
77 InstructionType::Bool => "bool".to_string(),
78 InstructionType::Vec(content) => format!("Vec<{}>", type_from_account_field_impl(*content)),
79 InstructionType::Option(option) => format!("Option<{}>", type_from_account_field_impl(*option)),
80 InstructionType::Defined(defined) => defined,
81 InstructionType::Array(content, number) => format!("[{}; {}]", type_from_account_field_impl(*content), number),
82 InstructionType::Bytes => "Vec<u8>".to_string(),
83 InstructionType::I128 => "i128".to_string(),
84 InstructionType::I16 => "i16".to_string(),
85 InstructionType::I32 => "i32".to_string(),
86 InstructionType::I64 => "i64".to_string(),
87 InstructionType::I8 => "i8".to_string(),
88 InstructionType::Tuple(content) => {
89 let mut tuple = "(".to_string();
90 for (i, inner_content) in content.iter().enumerate() {
91 tuple.push_str(&type_from_account_field_impl(inner_content.clone()));
92 if i < content.iter().len() - 1 {
93 tuple.push_str(", ");
94 }
95 }
96 tuple.push_str(")");
97 tuple
98 }
99 InstructionType::PublicKey => "Pubkey".to_string(),
100 InstructionType::pubkey => "Pubkey".to_string(),
101 InstructionType::HashMap(content_a, content_b) => format!("HashMap<{}, {}>", type_from_account_field_impl(*content_a), type_from_account_field_impl(*content_b)),
102 InstructionType::BTreeMap(content_a, content_b) => format!("BTreeMap<{}, {}>", type_from_account_field_impl(*content_a), type_from_account_field_impl(*content_b)),
103 InstructionType::HashSet(content) => format!("HashSet<{}>", type_from_account_field_impl(*content)),
104 InstructionType::BTreeSet(content) => format!("BTreeSet<{}>", type_from_account_field_impl(*content)),
105 }
106}