use std::collections::HashMap;
pub struct Enum {
values: HashMap<String, i32>,
}
impl Enum {
pub fn new(values: HashMap<String, i32>) -> Self {
Enum { values }
}
pub fn find(&self, key: &str) -> Option<i32> {
self.values.get(key).cloned()
}
}
pub struct Symbols {
list: Vec<String>,
enum_obj: Enum,
}
impl Symbols {
pub fn new(symbols: Vec<String>) -> Self {
let enum_obj = Enum::new(symbols.iter().enumerate().map(|(i, s)| (s.clone(), i as i32)).collect());
Symbols {
list: symbols,
enum_obj,
}
}
pub fn add(&mut self, symbol: String) -> Option<usize> {
if !symbol.is_empty() {
if let Some(&index) = self.enum_obj.find(&symbol) {
return Some(index as usize);
} else {
let index = self.list.len();
self.list.push(symbol.clone());
self.enum_obj.values.insert(symbol, index as i32);
return Some(index);
}
}
None
}
pub fn fetch(&self, payload: i32) -> (String, usize) {
match payload {
index if index >= 0 && index < self.list.len() as i32 => {
let symbol = self.list[index as usize].clone();
(symbol, index as usize)
}
_ => ("".to_string(), -1),
}
}
pub fn find(&self, symbol: &str) -> Option<usize> {
self.enum_obj.find(symbol).map(|index| index as usize)
}
pub fn get(&self, index: usize) -> Option<&str> {
self.list.get(index).map(|s| s.as_str())
}
pub fn get_symbols(&self) -> &[String] {
&self.list
}
pub fn reset(&mut self, symbols: Vec<String>) {
self.list = symbols;
self.enum_obj = Enum::new(symbols.iter().enumerate().map(|(i, s)| (s.clone(), i as i32)).collect());
}
}
pub fn extract_symbol(index: i32, context: &dyn Any, options: &dyn Any) -> String {
if let Some(get_symbol) = options.get_symbol {
if let Some(symbol) = get_symbol(index, context, options) {
return symbol;
}
}
index.to_string()
}
pub fn ensure_symbol_index(symbol: &str, context: &dyn Any, options: &dyn Any) -> Result<i32, String> {
if let Some(add_symbol) = options.add_symbol {
if let Some(index) = add_symbol(symbol, context, options) {
return Ok(index);
}
}
Err(symbol.to_string())
}
pub fn recursive_symbol_extraction(key: &str, value: &dyn Any, context: &dyn Any, options: &dyn Any) -> Box<dyn Any> {
if key.starts_with('$') {
if let Some(get_symbol) = options.get_symbol {
let recursive_fix = |value: &dyn Any| -> Box<dyn Any> {
if let Some(array) = value.downcast_ref::<Vec<Box<dyn Any>>>() {
let mut new_array = Vec::new();
for item in array {
new_array.push(recursive_fix(item));
}
return Box::new(new_array);
} else if let Some(number) = value.downcast_ref::<i32>() {
if let Some(symbol) = get_symbol(*number, context, options) {
return Box::new(symbol);
}
} else if let Some(object) = value.downcast_ref::<HashMap<String, Box<dyn Any>>>() {
let mut new_object = HashMap::new();
for (key, value) in object {
new_object.insert(key.clone(), recursive_fix(value));
}
return Box::new(new_object);
}
Box::new(value.clone())
};
return recursive_fix(value);
}
}
Box::new(value.clone())
}
pub fn recursive_symbol_indexes_ensured(key: &str, value: &dyn Any, context: &dyn Any, options: &dyn Any) -> Box<dyn Any> {
if key.starts_with('$') {
if let Some(add_symbol) = options.add_symbol {
let recursive_fix = |value: &dyn Any| -> Box<dyn Any> {
if let Some(array) = value.downcast_ref::<Vec<Box<dyn Any>>>() {
let mut new_array = Vec::new();
for item in array {
new_array.push(recursive_fix(item));
}
return Box::new(new_array);
} else if let Some(string) = value.downcast_ref::<String>() {
if let Ok(index) = add_symbol(string, context, options) {
return Box::new(index);
}
} else if let Some(object) = value.downcast_ref::<HashMap<String, Box<dyn Any>>>() {
let mut new_object = HashMap::new();
for (key, value) in object {
new_object.insert(key.clone(), recursive_fix(value));
}
return Box::new(new_object);
}
Box::new(value.clone())
};
return recursive_fix(value);
}
}
Box::new(value.clone())
}