use serde::{Deserialize, Serialize};
use std::io::{Read, Write};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ManifestError {
#[error("I/O error while reading manifest")]
Io(#[from] std::io::Error),
#[error("failed to parse manifest")]
TomlDeserialize(#[from] toml::de::Error),
#[error("failed to write manifest")]
TomlSerialize(#[from] toml::ser::Error),
#[error("`manifest.toml` not found in {path}")]
NotFound { path: std::path::PathBuf },
}
#[derive(Serialize, Deserialize)]
pub struct Library {
pub description: Option<String>,
pub version: semver::Version,
pub authors: Option<Vec<String>>,
}
impl Default for Library {
fn default() -> Self {
Self {
description: Some(String::from("µcad standard library")),
version: crate::version(),
authors: Some(
[
String::from("Patrick Hoffmann"),
String::from("Michael Winkelmann"),
]
.into(),
),
}
}
}
#[derive(Serialize, Deserialize, Default)]
pub struct Manifest {
pub library: Library,
}
impl Manifest {
pub fn load(path: impl AsRef<std::path::Path>) -> Result<Self, ManifestError> {
let manifest_path = Self::manifest_path(&path);
if !manifest_path.exists() || !manifest_path.is_file() {
return Err(ManifestError::NotFound {
path: std::path::PathBuf::from(path.as_ref()),
});
}
let mut file = std::fs::File::open(manifest_path)?;
let mut buf = String::new();
file.read_to_string(&mut buf)?;
Ok(toml::from_str(&buf)?)
}
pub fn save(&self, path: impl AsRef<std::path::Path>) -> Result<(), ManifestError> {
let s = toml::to_string(&self)?;
let mut file = std::fs::File::create(Self::manifest_path(path))?;
file.write_all(s.as_bytes())?;
Ok(())
}
pub fn manifest_path(path: impl AsRef<std::path::Path>) -> std::path::PathBuf {
path.as_ref().join("manifest.toml")
}
}