wasmer_cli/commands/run/
target.rs1use std::{
2 fs::File,
3 io::Read as _,
4 path::{Path, PathBuf},
5 sync::Arc,
6};
7
8use anyhow::{Context as _, Error, bail};
9use indicatif::ProgressBar;
10use wasmer::Module;
11#[cfg(feature = "compiler")]
12use wasmer_compiler::ArtifactBuild;
13use wasmer_types::ModuleHash;
14use wasmer_wasix::{
15 Runtime,
16 bin_factory::BinaryPackage,
17 runtime::{module_cache::HashedModuleData, task_manager::VirtualTaskManagerExt as _},
18};
19
20#[derive(Debug, Clone)]
23pub enum TargetOnDisk {
24 WebAssemblyBinary,
25 Wat,
26 LocalWebc,
27 Artifact,
28}
29
30impl TargetOnDisk {
31 pub fn from_file(path: &Path) -> Result<TargetOnDisk, Error> {
32 let mut buffer = [0_u8; 512];
35
36 let mut f = File::open(path)
37 .with_context(|| format!("Unable to open \"{}\" for reading", path.display()))?;
38 let bytes_read = f.read(&mut buffer)?;
39
40 let leading_bytes = &buffer[..bytes_read];
41
42 if wasmer::is_wasm(leading_bytes) {
43 return Ok(TargetOnDisk::WebAssemblyBinary);
44 }
45
46 if webc::detect(leading_bytes).is_ok() {
47 return Ok(TargetOnDisk::LocalWebc);
48 }
49
50 #[cfg(feature = "compiler")]
51 if ArtifactBuild::is_deserializable(leading_bytes) {
52 return Ok(TargetOnDisk::Artifact);
53 }
54
55 match path.extension().and_then(|s| s.to_str()) {
59 Some("wat") => Ok(TargetOnDisk::Wat),
60 Some("wasm") => Ok(TargetOnDisk::WebAssemblyBinary),
61 Some("webc") => Ok(TargetOnDisk::LocalWebc),
62 Some("wasmu") => Ok(TargetOnDisk::WebAssemblyBinary),
63 _ => bail!("Unable to determine how to execute \"{}\"", path.display()),
64 }
65 }
66}
67
68#[allow(clippy::large_enum_variant)]
69#[derive(Debug, Clone)]
70pub enum ExecutableTarget {
71 WebAssembly {
72 module: Module,
73 module_hash: ModuleHash,
74 path: PathBuf,
75 },
76 Package(Box<BinaryPackage>),
77}
78
79impl ExecutableTarget {
80 #[tracing::instrument(level = "debug", skip_all)]
83 pub fn from_dir(
84 dir: &Path,
85 runtime: &Arc<dyn Runtime + Send + Sync>,
86 pb: &ProgressBar,
87 ) -> Result<Self, Error> {
88 pb.set_message(format!("Loading \"{}\" into memory", dir.display()));
89 pb.set_message("Resolving dependencies");
90 let inner_runtime = runtime.clone();
91 let pkg = runtime.task_manager().spawn_and_block_on({
92 let path = dir.to_path_buf();
93
94 async move { BinaryPackage::from_dir(&path, inner_runtime.as_ref()).await }
95 })??;
96
97 Ok(ExecutableTarget::Package(Box::new(pkg)))
98 }
99
100 #[tracing::instrument(level = "debug", skip_all)]
102 pub fn from_file(
103 path: &Path,
104 runtime: &Arc<dyn Runtime + Send + Sync>,
105 pb: &ProgressBar,
106 ) -> Result<Self, Error> {
107 pb.set_message(format!("Loading from \"{}\"", path.display()));
108
109 match TargetOnDisk::from_file(path)? {
110 TargetOnDisk::WebAssemblyBinary | TargetOnDisk::Wat => {
111 let wasm = std::fs::read(path)?;
112 let module_data = HashedModuleData::new(wasm);
113 let module_hash = *module_data.hash();
114
115 pb.set_message("Compiling to WebAssembly");
116 let module = runtime
117 .load_hashed_module_sync(module_data, None)
118 .with_context(|| format!("Unable to compile \"{}\"", path.display()))?;
119
120 Ok(ExecutableTarget::WebAssembly {
121 module,
122 module_hash,
123 path: path.to_path_buf(),
124 })
125 }
126 TargetOnDisk::Artifact => {
127 let engine = runtime.engine();
128 pb.set_message("Deserializing pre-compiled WebAssembly module");
129 let module = unsafe { Module::deserialize_from_file(&engine, path)? };
130
131 let module_hash = module.info().hash.ok_or_else(|| {
132 anyhow::Error::msg("module hash is not present in the artifact")
133 })?;
134
135 Ok(ExecutableTarget::WebAssembly {
136 module,
137 module_hash,
138 path: path.to_path_buf(),
139 })
140 }
141 TargetOnDisk::LocalWebc => {
142 let container = wasmer_package::utils::from_disk(path)?;
143 pb.set_message("Resolving dependencies");
144
145 let inner_runtime = runtime.clone();
146 let pkg = runtime.task_manager().spawn_and_block_on(async move {
147 BinaryPackage::from_webc(&container, inner_runtime.as_ref()).await
148 })??;
149 Ok(ExecutableTarget::Package(Box::new(pkg)))
150 }
151 }
152 }
153}