#[cfg(feature = "constructor-packaging")]
pub mod constructor_provider;
pub mod platform;
#[cfg(feature = "constructor-packaging")]
pub mod provider_bundle;
pub mod types;
pub mod validation;
#[cfg(test)]
mod tests;
pub use platform::{detect_current_platform, SUPPORTED_TARGETS};
pub use types::{CargoToml, CompileOptions};
use anyhow::{bail, Result};
use std::path::PathBuf;
pub fn package_workflow(project_path: PathBuf, output_path: PathBuf) -> Result<()> {
validation::validate_rust_crate_structure(&project_path)?;
let cargo_toml = validation::validate_cargo_toml(&project_path)?;
validation::validate_cloacina_compatibility(&cargo_toml)?;
validation::validate_packaged_workflow_presence(&project_path)?;
let package_toml_path = project_path.join("package.toml");
if !package_toml_path.exists() {
bail!(
"package.toml not found in project directory: {:?}. \
Create a package.toml with [package] name, version, interface, interface_version, \
and extension = \"cloacina\" fields.",
project_path
);
}
fidius_core::package::pack_package(&project_path, Some(&output_path))
.map_err(|e| anyhow::anyhow!("Failed to pack package: {}", e))?;
Ok(())
}
pub fn parse_duration_str(s: &str) -> Result<std::time::Duration, String> {
let s = s.trim();
if s.is_empty() {
return Err("empty string".to_string());
}
let (num_str, suffix) = if let Some(stripped) = s.strip_suffix("ms") {
(stripped, "ms")
} else {
let split = s.len() - 1;
if split == 0 || !s.as_bytes()[split].is_ascii_alphabetic() {
return Err(format!(
"expected number followed by unit (s, m, h, ms), got '{s}'"
));
}
(&s[..split], &s[split..])
};
let value: u64 = num_str
.parse()
.map_err(|_| format!("'{num_str}' is not a valid number"))?;
match suffix {
"ms" => Ok(std::time::Duration::from_millis(value)),
"s" => Ok(std::time::Duration::from_secs(value)),
"m" => Ok(std::time::Duration::from_secs(value * 60)),
"h" => Ok(std::time::Duration::from_secs(value * 3600)),
other => Err(format!("unknown unit '{other}', expected s, m, h, or ms")),
}
}