soda_sol 0.1.1

Generates Solana Projects from an IDL
Documentation
use crate::{structs, Error};
use handlebars::{handlebars_helper, Handlebars};
use structs::{InstructionType, TemplateHelper, IDL};

pub(crate) fn create_handlebars_registry() -> Handlebars<'static> {
    handlebars_helper!(snakecase: |name: String| name.chars().enumerate().fold(
            "".to_string(),
            |acc, (index, letter)| {
                if letter.is_uppercase() {
                    if index == 0 {
                        format!("{}{}", acc, letter.to_lowercase())
                    } else {
                        format!("{}_{}", acc, letter.to_lowercase())
                    }
                } else {
                    format!("{}{}", acc, letter)
                }
            }
        )
    );

    handlebars_helper!(pascalcase: |name: String|{
            let mut passcalcase_chars: Vec<char> = name.chars().collect();
            if passcalcase_chars.is_empty() {
                "".to_string()
            } else {
            let first: Vec<char> = passcalcase_chars[0].to_uppercase().to_string().chars().collect();
            passcalcase_chars[0] = *first.first().unwrap_or(&' ');
            let passcalcase: String = passcalcase_chars.into_iter().collect();
            passcalcase
            }
        }
    );

    handlebars_helper!(type_from_account_field: |account_field_type: InstructionType| type_from_account_field_impl(account_field_type));

    handlebars_helper!(debug_idl: |idl: IDL|serde_json::to_string(&idl).unwrap_or("".to_string()));

    let mut handlebars = Handlebars::new();

    handlebars.register_helper("snakecase", Box::new(snakecase));
    handlebars.register_helper("pascalcase", Box::new(pascalcase));
    handlebars.register_helper("type_from_account_field", Box::new(type_from_account_field));
    handlebars.register_helper("debug_idl", Box::new(debug_idl));
    handlebars
}

pub fn apply_user_helpers(
    helpers: Vec<TemplateHelper>,
    handlebars: &mut handlebars::Handlebars,
) -> Result<(), Error> {
    for TemplateHelper {
        helper_name,
        script,
    } in helpers
    {
        match handlebars.register_script_helper(&helper_name, &script) {
            Ok(_) => {}
            Err(err) => {
                return Err(Error::CustomError {
                    message: format!("Error registering helper: {}", err),
                })
            }
        }
    }
    Ok(())
}

fn type_from_account_field_impl(account_field_type:  InstructionType) -> String {
    match account_field_type {
        InstructionType::String => "String".to_string(),
        InstructionType::U8 => "u8".to_string(),
        InstructionType::U16 => "u16".to_string(),
        InstructionType::U32 => "u32".to_string(),
        InstructionType::U64 => "u64".to_string(),
        InstructionType::U128 => "u128".to_string(),
        InstructionType::Bool => "bool".to_string(),
        InstructionType::Vec(content) => format!("Vec<{}>", type_from_account_field_impl(*content)),
        InstructionType::Option(option) => format!("Option<{}>", type_from_account_field_impl(*option)),
        InstructionType::Defined(defined) => defined,
        InstructionType::Array(content, number) => format!("[{}; {}]", type_from_account_field_impl(*content), number),
        InstructionType::Bytes => "Vec<u8>".to_string(),
        InstructionType::I128 => "i128".to_string(),
        InstructionType::I16 => "i16".to_string(),
        InstructionType::I32 => "i32".to_string(),
        InstructionType::I64 => "i64".to_string(),
        InstructionType::I8 => "i8".to_string(),
        InstructionType::Tuple(content) => {
            let mut tuple = "(".to_string();
            for (i, inner_content) in content.iter().enumerate() {
                tuple.push_str(&type_from_account_field_impl(inner_content.clone()));
                if i < content.iter().len() - 1 {
                    tuple.push_str(", ");
                }
            }
            tuple.push_str(")");
            tuple
        }
        InstructionType::PublicKey => "Pubkey".to_string(),
        InstructionType::pubkey => "Pubkey".to_string(),
        InstructionType::HashMap(content_a, content_b) => format!("HashMap<{}, {}>", type_from_account_field_impl(*content_a), type_from_account_field_impl(*content_b)),
        InstructionType::BTreeMap(content_a, content_b) => format!("BTreeMap<{}, {}>", type_from_account_field_impl(*content_a), type_from_account_field_impl(*content_b)),
        InstructionType::HashSet(content) => format!("HashSet<{}>", type_from_account_field_impl(*content)),
        InstructionType::BTreeSet(content) => format!("BTreeSet<{}>", type_from_account_field_impl(*content)),
    }    
}