use std::path::{Path, PathBuf};
use super::{LeanLibrary, LeanModule};
use crate::error::LeanResult;
use crate::runtime::LeanRuntime;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LeanModuleInitializer {
package: String,
module: String,
}
impl LeanModuleInitializer {
#[must_use]
pub fn new(package: impl Into<String>, module: impl Into<String>) -> Self {
Self {
package: package.into(),
module: module.into(),
}
}
#[must_use]
pub fn package_name(&self) -> &str {
&self.package
}
#[must_use]
pub fn module_name(&self) -> &str {
&self.module
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LeanLibraryDependency {
path: PathBuf,
exports_symbols_for_dependents: bool,
initializer: Option<LeanModuleInitializer>,
}
impl LeanLibraryDependency {
#[must_use]
pub fn path(path: impl Into<PathBuf>) -> Self {
Self {
path: path.into(),
exports_symbols_for_dependents: false,
initializer: None,
}
}
#[must_use]
pub fn export_symbols_for_dependents(mut self) -> Self {
self.exports_symbols_for_dependents = true;
self
}
#[must_use]
pub fn initializer(mut self, package: impl Into<String>, module: impl Into<String>) -> Self {
self.initializer = Some(LeanModuleInitializer::new(package, module));
self
}
#[must_use]
pub fn path_ref(&self) -> &Path {
&self.path
}
#[must_use]
pub fn exports_symbols_for_dependents(&self) -> bool {
self.exports_symbols_for_dependents
}
#[must_use]
pub fn module_initializer(&self) -> Option<&LeanModuleInitializer> {
self.initializer.as_ref()
}
}
pub struct LeanLibraryBundle<'lean> {
primary: LeanLibrary<'lean>,
dependencies: Vec<LeanLibrary<'lean>>,
}
impl<'lean> LeanLibraryBundle<'lean> {
pub fn open(
runtime: &'lean LeanRuntime,
primary_path: impl AsRef<Path>,
dependencies: impl IntoIterator<Item = LeanLibraryDependency>,
) -> LeanResult<Self> {
let mut opened_dependencies = Vec::new();
for dependency in dependencies {
let library = if dependency.exports_symbols_for_dependents {
LeanLibrary::open_globally(runtime, &dependency.path)?
} else {
LeanLibrary::open(runtime, &dependency.path)?
};
if let Some(initializer) = dependency.initializer {
let _module = library.initialize_module(&initializer.package, &initializer.module)?;
}
opened_dependencies.push(library);
}
let primary = LeanLibrary::open(runtime, primary_path)?;
Ok(Self {
primary,
dependencies: opened_dependencies,
})
}
pub fn initialize_module<'bundle>(
&'bundle self,
package: &str,
module: &str,
) -> LeanResult<LeanModule<'lean, 'bundle>> {
self.primary.initialize_module(package, module)
}
#[must_use]
pub fn library(&self) -> &LeanLibrary<'lean> {
&self.primary
}
#[must_use]
pub fn dependency_count(&self) -> usize {
self.dependencies.len()
}
}
impl std::fmt::Debug for LeanLibraryBundle<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LeanLibraryBundle")
.field("primary", &self.primary)
.field("dependency_count", &self.dependencies.len())
.finish()
}
}