use std::collections::HashSet;
use super::*;
#[derive(Default, Clone)]
pub struct Context {
pub cdylib: Option<String>,
pub current_config: Option<PythonConfig>,
pub module_namespace: Option<String>,
pub recursive_type_names: HashSet<String>,
pub builtin_types: Option<BuiltinTypes>,
}
impl Context {
pub fn update_from_root(&mut self, root: &general::Root) -> Result<()> {
self.cdylib = root.cdylib.clone();
self.builtin_types = Some(root.builtin_types.clone().map_node(self)?);
Ok(())
}
pub fn update_from_namespace(&mut self, namespace: &general::Namespace) -> Result<()> {
self.current_config = Some(match &namespace.config_toml {
Some(toml) => PythonConfig::from_uniffi_toml(toml)?,
None => PythonConfig::default(),
});
self.module_namespace = Some(namespace.name.clone());
let mut recursive_type_names = HashSet::new();
namespace.visit(|e: &general::Enum| {
if e.recursive {
recursive_type_names.insert(e.name.clone());
}
});
namespace.visit(|r: &general::Record| {
if r.recursive {
recursive_type_names.insert(r.name.clone());
}
});
self.recursive_type_names = recursive_type_names;
Ok(())
}
pub fn builtin_types(&self) -> Result<BuiltinTypes> {
self.builtin_types
.clone()
.ok_or_else(|| anyhow!("Context.builtin_types not set"))
}
pub fn is_recursive(&self, name: &str) -> bool {
self.recursive_type_names.contains(name)
}
pub fn module_namespace(&self) -> Result<&str> {
self.module_namespace
.as_deref()
.ok_or_else(|| anyhow!("Context.module_namespace not set"))
}
pub fn config(&self) -> Result<&PythonConfig> {
self.current_config
.as_ref()
.ok_or_else(|| anyhow!("Context.config not set"))
}
pub fn cdylib(&self) -> Result<String> {
let default_cdylib = self.cdylib.as_deref().unwrap_or("uniffi");
Ok(match &self.config()?.cdylib_name {
Some(cdylib) => cdylib.clone(),
None => default_cdylib.to_string(),
})
}
pub fn external_package_name(&self, namespace: &str) -> Result<Option<String>> {
match &self.module_namespace {
None => bail!("Config.module_namespace not set"),
Some(current_namespace) if current_namespace == namespace => return Ok(None),
_ => (),
}
let config = self.config()?;
Ok(Some(match config.external_packages.get(namespace) {
None => namespace.to_string(),
Some(package_name) if package_name.is_empty() => namespace.to_string(),
Some(package_name) => package_name.clone(),
}))
}
pub fn custom_type_config(
&self,
custom: &general::CustomType,
) -> Result<Option<CustomTypeConfig>> {
Ok(self.config()?.custom_types.get(&custom.orig_name).cloned())
}
}