use crate::paths;
use anyhow::{Context, Result};
use std::path::Path;
pub struct RustTemplates;
impl RustTemplates {
pub fn new() -> Self {
Self
}
pub async fn create_cargo_toml(&self, path: &Path, project_name: &str, assets_root: &Path) -> Result<()> {
let template_path = assets_root.join("project/Cargo.toml.prod.template");
let template = tokio::fs::read_to_string(&template_path)
.await
.with_context(|| format!("Failed to read {:?} from downloaded mecha10-assets", template_path))?;
let content = template.replace("{{project_name}}", project_name);
tokio::fs::write(path.join(paths::rust::CARGO_TOML), content).await?;
Ok(())
}
pub async fn create_main_rs(&self, path: &Path, project_name: &str, assets_root: &Path) -> Result<()> {
let template_path = assets_root.join("project/main.rs.template");
let template = tokio::fs::read_to_string(&template_path)
.await
.with_context(|| format!("Failed to read {:?} from downloaded mecha10-assets", template_path))?;
let content = template.replace("{{project_name}}", project_name);
let src_dir = path.join(paths::project::SRC_DIR);
tokio::fs::create_dir_all(&src_dir).await?;
tokio::fs::write(path.join(paths::rust::MAIN_RS), content).await?;
Ok(())
}
pub async fn create_build_rs(&self, path: &Path, assets_root: &Path) -> Result<()> {
let template_path = assets_root.join("project/build.rs.template");
let content = tokio::fs::read_to_string(&template_path)
.await
.with_context(|| format!("Failed to read {:?} from downloaded mecha10-assets", template_path))?;
tokio::fs::write(path.join(paths::rust::BUILD_RS), content).await?;
Ok(())
}
pub async fn create_rustfmt_toml(&self, path: &Path, assets_root: &Path) -> Result<()> {
let template_path = assets_root.join("project/rustfmt.toml.template");
let content = tokio::fs::read_to_string(&template_path)
.await
.with_context(|| format!("Failed to read {:?} from downloaded mecha10-assets", template_path))?;
tokio::fs::write(path.join(paths::rust::RUSTFMT_TOML), content).await?;
Ok(())
}
}
impl Default for RustTemplates {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn stage_assets_root_with(name: &str, content: &str) -> tempfile::TempDir {
let assets_root = tempfile::tempdir().unwrap();
let project_dir = assets_root.path().join("project");
std::fs::create_dir_all(&project_dir).unwrap();
std::fs::write(project_dir.join(name), content).unwrap();
assets_root
}
#[tokio::test]
async fn create_build_rs_reads_from_mecha10_assets_and_writes_project_file() {
let assets_root = stage_assets_root_with("build.rs.template", "fn main() {}\n");
let dest = tempfile::tempdir().unwrap();
RustTemplates::new()
.create_build_rs(dest.path(), assets_root.path())
.await
.unwrap();
let content = tokio::fs::read_to_string(dest.path().join("build.rs")).await.unwrap();
assert_eq!(content, "fn main() {}\n");
}
#[tokio::test]
async fn create_main_rs_replaces_project_name_placeholder() {
let assets_root = stage_assets_root_with("main.rs.template", "// {{project_name}}\n");
let dest = tempfile::tempdir().unwrap();
RustTemplates::new()
.create_main_rs(dest.path(), "my-robot", assets_root.path())
.await
.unwrap();
let content = tokio::fs::read_to_string(dest.path().join("src/main.rs"))
.await
.unwrap();
assert_eq!(content, "// my-robot\n");
}
#[tokio::test]
async fn create_rustfmt_toml_reads_from_mecha10_assets_and_writes_project_file() {
let assets_root = stage_assets_root_with("rustfmt.toml.template", "edition = \"2021\"\n");
let dest = tempfile::tempdir().unwrap();
RustTemplates::new()
.create_rustfmt_toml(dest.path(), assets_root.path())
.await
.unwrap();
let content = tokio::fs::read_to_string(dest.path().join("rustfmt.toml"))
.await
.unwrap();
assert_eq!(content, "edition = \"2021\"\n");
}
}