1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use crate::config::JamsocketConfig;
use anyhow::{anyhow, Result};
use cargo_metadata::Message;
use jamsocket_server::Server;
use jamsocket_wasm_host::WasmHostFactory;
use std::{
fs::read_to_string,
path::PathBuf,
process::{Command, Stdio},
};
pub fn locate_config() -> anyhow::Result<JamsocketConfig> {
if let Ok(r) = read_to_string("jamsocket.toml") {
tracing::info!("Loading config from file (jamsocket.toml)");
toml::from_str(&r).map_err(|e| e.into())
} else {
tracing::info!("Didn't find a jamsocket.toml file in current directory, using default");
Ok(JamsocketConfig::default())
}
}
pub fn run_cargo_build_command(
package: &Option<String>,
target: &str,
release: bool,
) -> Result<PathBuf> {
let mut build_command = Command::new("cargo");
build_command.stdout(Stdio::piped());
build_command.arg("build");
build_command.args(["--message-format", "json-render-diagnostics"]);
if let Some(package) = package {
build_command.args(["--package", package]);
}
build_command.args(["--target", target]);
if release {
build_command.arg("--release");
}
let mut build_command = build_command.spawn()?;
let reader = std::io::BufReader::new(
build_command
.stdout
.take()
.ok_or_else(|| anyhow!("Could not read stdout stream."))?,
);
let mut found_wasm_modules = Vec::new();
for message in cargo_metadata::Message::parse_stream(reader) {
match message {
Ok(Message::CompilerArtifact(artifact)) => {
for filename in artifact.filenames {
if filename
.extension()
.map_or(false, |ext| ext.to_ascii_lowercase() == "wasm")
{
found_wasm_modules.push(filename);
}
}
}
Ok(Message::BuildFinished(finished)) => {
if !finished.success {
return Err(anyhow!("Build error."));
}
}
Err(e) => return Err(anyhow!("Unknown error during build: {:?}.", e)),
_ => (),
}
}
build_command
.wait()
.map_err(|e| anyhow!("Encountered OS error running build subprocess: {:?}", e))?;
let result = match found_wasm_modules.as_slice() {
[] => return Err(anyhow!("No .wasm files emitted by build.")),
[a] => a,
_ => return Err(anyhow!("Multiple .wasm files emitted by build.")),
};
Ok(result.into())
}
pub fn dev() -> anyhow::Result<()> {
let config = locate_config()?;
tracing::info!("Building service");
let service_wasm = run_cargo_build_command(&config.service.package, "wasm32-wasi", true)?;
let host_factory = WasmHostFactory::new(service_wasm)?;
Server::default().serve(host_factory).map_err(|e| e.into())
}