use std::{
fs::{create_dir_all, OpenOptions},
io::{Read, Seek, Write},
path::Path,
};
use anyhow::{anyhow, Result};
use toml::{value::Table, Value};
pub(crate) fn start() -> Result<()> {
if !Path::new("Cargo.toml").exists() {
return Err(anyhow!("Must be called inside a cargo project"));
}
create_dir_all(".cargo").unwrap();
let mut config_toml = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(".cargo/config.toml")
.unwrap();
let mut content = String::new();
config_toml.read_to_string(&mut content).unwrap();
let mut content = content.parse::<Value>().unwrap();
let table = content
.as_table_mut()
.expect("wrong .cargo/config.toml` format");
match table.get_mut("build") {
Some(value) => {
let build = value
.as_table_mut()
.expect("wrong `.cargo/config.toml` format");
match build.get_mut("target") {
Some(target)
if target.as_str().expect("wrong `.cargo/config.toml` format")
!= "wasm32-wasi" =>
{
return Err(
anyhow!("value `build.target` inside `.cargo/config.toml` already set to something else than `wasm32-wasi`")
);
}
None => {
build.insert("target".to_owned(), Value::String("wasm32-wasi".to_owned()));
}
_ => {
}
}
}
None => {
let mut new_build = Table::new();
new_build.insert("target".to_owned(), Value::String("wasm32-wasi".to_owned()));
table.insert("build".to_owned(), Value::Table(new_build));
}
};
match table.get_mut("target") {
Some(value) => {
let target = value
.as_table_mut()
.expect("wrong `.cargo/config.toml` format");
match target.get_mut("wasm32-wasi") {
Some(value) => {
let target = value
.as_table_mut()
.expect("wrong `.cargo/config.toml` format");
match target.get_mut("runner") {
Some(runner)
if runner.as_str().expect("wrong `.cargo/config.toml` format")
== "lunatic" =>
{
target.insert(
"runner".to_owned(),
Value::String("lunatic run".to_owned()),
);
}
Some(runner)
if runner.as_str().expect("wrong `.cargo/config.toml` format")
!= "lunatic run" =>
{
return Err(
anyhow!("value `target.wasm32-wasi.runner` inside `.cargo/config.toml` already set to something else than `lunatic run`")
);
}
None => {
target.insert(
"runner".to_owned(),
Value::String("lunatic run".to_owned()),
);
}
_ => {
}
}
}
None => {
let mut new_wasm32_wasi = Table::new();
new_wasm32_wasi
.insert("runner".to_owned(), Value::String("lunatic run".to_owned()));
target.insert("wasm32-wasi".to_owned(), Value::Table(new_wasm32_wasi));
}
}
}
None => {
let mut new_wasm32_wasi = Table::new();
new_wasm32_wasi.insert("runner".to_owned(), Value::String("lunatic run".to_owned()));
let mut new_target = Table::new();
new_target.insert("wasm32-wasi".to_owned(), Value::Table(new_wasm32_wasi));
table.insert("target".to_owned(), Value::Table(new_target));
}
};
let new_config = toml::to_string(table).unwrap();
config_toml.set_len(0).unwrap();
config_toml.rewind().unwrap();
config_toml
.write_all(new_config.as_bytes())
.expect("unable to write new config to `.cargo/config.toml`");
println!("Cargo project initialized!");
Ok(())
}