use std::path::PathBuf;
pub(crate) mod cpp;
pub(crate) mod csharp;
pub(crate) mod js_quickjs;
pub(crate) mod lua;
pub(crate) mod python;
pub(crate) mod rust;
use crate::ir::ResolvedContract;
use crate::ir::ResolvedDependency;
use crate::ir::ValidatedIr;
use polyplug_codegen::PolyplugcError;
pub(crate) const CALL_ARENA_BUF_LEN: usize = 512;
pub(crate) fn collect_peer_contracts(ir: &ValidatedIr) -> Vec<&ResolvedContract> {
let deps: &[ResolvedDependency] = match ir.bundle.as_ref() {
Some(b) => &b.dependencies,
None => return Vec::new(),
};
ir.contracts
.iter()
.filter(|c: &&ResolvedContract| {
deps.iter().any(|d: &ResolvedDependency| {
let dep_contract_id: u64 = match d {
ResolvedDependency::ByContract { contract_id, .. } => *contract_id,
ResolvedDependency::ByBundle { contract_id, .. } => *contract_id,
};
dep_contract_id == c.contract_id
})
})
.collect()
}
pub(crate) fn peer_min_version(ir: &ValidatedIr, target_contract_id: u64) -> u32 {
let deps: &[ResolvedDependency] = match ir.bundle.as_ref() {
Some(b) => &b.dependencies,
None => return 0,
};
for d in deps {
match d {
ResolvedDependency::ByContract {
contract_id,
min_version,
..
} if *contract_id == target_contract_id => return *min_version,
ResolvedDependency::ByBundle {
contract_id,
min_version,
..
} if *contract_id == target_contract_id => return *min_version,
_ => {}
}
}
0
}
pub fn is_native_runtime(runtime: &str) -> bool {
runtime.to_lowercase() == "native"
}
pub(crate) fn emit_manifest_dependencies(dependencies: &[ResolvedDependency]) -> String {
let mut dep_toml: String = String::new();
for dep in dependencies {
dep_toml.push_str("\n[[dependency]]\n");
match dep {
ResolvedDependency::ByContract {
contract,
contract_id,
min_version,
} => {
dep_toml.push_str("kind = \"contract\"\n");
dep_toml.push_str(&format!("contract = \"{contract}\"\n"));
dep_toml.push_str(&format!("contract_id = 0x{contract_id:016X}\n"));
dep_toml.push_str(&format!("min_version = \"{min_version}.0\"\n"));
}
ResolvedDependency::ByBundle {
bundle,
bundle_id,
contract,
contract_id,
min_version,
} => {
dep_toml.push_str("kind = \"bundle\"\n");
dep_toml.push_str(&format!("bundle = \"{bundle}\"\n"));
dep_toml.push_str(&format!("bundle_id = 0x{bundle_id:016X}\n"));
dep_toml.push_str(&format!("contract = \"{contract}\"\n"));
dep_toml.push_str(&format!("contract_id = 0x{contract_id:016X}\n"));
dep_toml.push_str(&format!("min_version = \"{min_version}.0\"\n"));
}
}
}
dep_toml
}
pub(crate) fn format_manifest_file_field(file: &polyplug_codegen::ResolvedBundleFile) -> String {
match file {
polyplug_codegen::ResolvedBundleFile::Single(path) => format!("file = \"{path}\""),
polyplug_codegen::ResolvedBundleFile::PlatformMap(map) => {
let mut lines: Vec<String> = Vec::with_capacity(map.len() + 1);
lines.push(String::from("[file]"));
let mut entries: Vec<(&str, &str, &str)> = map
.iter()
.map(|(k, v)| (k.os.as_str(), k.arch.as_str(), v.as_str()))
.collect();
entries.sort();
for (os, arch, path) in entries {
lines.push(format!("{os}.{arch} = \"{path}\""));
}
lines.join("\n")
}
}
}
#[derive(Debug)]
pub(crate) struct GeneratedFile {
pub path: PathBuf,
pub content: String,
pub force_regenerate: bool,
}
#[derive(Debug, Default)]
pub(crate) struct GeneratedFiles {
pub files: Vec<GeneratedFile>,
}
pub(crate) trait CodeGenerator {
fn generate_host(
&self,
ir: &ValidatedIr,
files: &mut GeneratedFiles,
) -> Result<(), PolyplugcError>;
fn generate_guest(
&self,
ir: &ValidatedIr,
files: &mut GeneratedFiles,
) -> Result<(), PolyplugcError>;
}