#![allow(dead_code)]
use crate::utils::to_pascal_case;
pub fn event_type_base_name(event_type: &str) -> &str {
event_type.rsplit("::").next().unwrap_or(event_type)
}
pub fn event_type_program(event_type: &str) -> Option<&str> {
event_type.rsplit_once("::").map(|(prefix, _)| prefix)
}
pub fn strip_event_type_suffix(event_type: &str) -> &str {
let base = event_type_base_name(event_type);
base.strip_suffix("IxState")
.or_else(|| base.strip_suffix("State"))
.unwrap_or(base)
}
pub fn scoped_event_type(program_name: &str, type_name: &str, is_instruction: bool) -> String {
let suffix = if is_instruction { "IxState" } else { "State" };
format!("{}::{}{}", program_name, type_name, suffix)
}
pub fn scoped_instruction_event_type(program_name: Option<&str>, instruction_name: &str) -> String {
let canonical_name = to_pascal_case(instruction_name);
match program_name {
Some(program_name) => format!("{}::{}IxState", program_name, canonical_name),
None => format!("{}IxState", canonical_name),
}
}
pub fn scoped_instruction_or_cpi_event_type(
program_name: Option<&str>,
event_name: &str,
is_cpi_event: bool,
) -> String {
if is_cpi_event {
match program_name {
Some(program_name) => format!("{}::{}CpiEvent", program_name, event_name),
None => format!("{}CpiEvent", event_name),
}
} else {
scoped_instruction_event_type(program_name, event_name)
}
}
pub fn canonicalize_instruction_event_type(event_type: &str) -> String {
let (program_name, base_name) = match event_type.rsplit_once("::") {
Some((program_name, base_name)) => (Some(program_name), base_name),
None => (None, event_type),
};
let instruction_name = base_name.strip_suffix("IxState").unwrap_or(base_name);
let canonical_name = to_pascal_case(instruction_name);
match program_name {
Some(program_name) => format!("{}::{}IxState", program_name, canonical_name),
None => format!("{}IxState", canonical_name),
}
}
pub fn canonicalize_event_type_name(event_type: &str) -> String {
if event_type.ends_with("IxState") {
canonicalize_instruction_event_type(event_type)
} else {
event_type.to_string()
}
}
use crate::parse::idl::IdlSpec;
pub type IdlLookup<'a> = &'a [(String, &'a IdlSpec)];
pub fn find_idl_for_type<'a>(type_str: &str, idls: IdlLookup<'a>) -> Option<&'a IdlSpec> {
if idls.is_empty() {
return None;
}
let first_segment = type_str.split("::").next()?.trim();
idls.iter()
.find(|(sdk_name, _)| sdk_name == first_segment)
.map(|(_, idl)| *idl)
.or_else(|| Some(idls[0].1))
}
pub fn program_name_for_type<'a>(type_str: &str, idls: IdlLookup<'a>) -> Option<&'a str> {
find_idl_for_type(type_str, idls).map(|idl| idl.get_name())
}
pub fn program_name_from_sdk_prefix(sdk_module: &str) -> &str {
sdk_module.strip_suffix("_sdk").unwrap_or(sdk_module)
}
pub fn snake_to_lower_camel(s: &str) -> String {
let mut result = String::with_capacity(s.len());
let mut capitalize_next = false;
for ch in s.chars() {
if ch == '_' {
capitalize_next = true;
} else if capitalize_next {
result.extend(ch.to_uppercase());
capitalize_next = false;
} else {
result.push(ch);
}
}
result
}
#[cfg(test)]
mod tests {
use super::{
canonicalize_event_type_name, canonicalize_instruction_event_type,
scoped_instruction_event_type, scoped_instruction_or_cpi_event_type,
};
#[test]
fn scoped_instruction_event_type_normalizes_snake_case_names() {
assert_eq!(
scoped_instruction_event_type(Some("pump"), "buy_exact_sol_in"),
"pump::BuyExactSolInIxState"
);
assert_eq!(
scoped_instruction_event_type(Some("pump"), "buy"),
"pump::BuyIxState"
);
}
#[test]
fn scoped_instruction_event_type_preserves_pascal_case_names() {
assert_eq!(
scoped_instruction_event_type(Some("ore"), "Deploy"),
"ore::DeployIxState"
);
}
#[test]
fn scoped_instruction_or_cpi_event_type_keeps_cpi_names_verbatim() {
assert_eq!(
scoped_instruction_or_cpi_event_type(Some("pump"), "TradeExecuted", true),
"pump::TradeExecutedCpiEvent"
);
}
#[test]
fn canonicalize_instruction_event_type_normalizes_scoped_snake_case() {
assert_eq!(
canonicalize_instruction_event_type("pump::create_v2IxState"),
"pump::CreateV2IxState"
);
}
#[test]
fn canonicalize_event_type_name_leaves_accounts_unchanged() {
assert_eq!(
canonicalize_event_type_name("pump::BondingCurveState"),
"pump::BondingCurveState"
);
}
}