use std::path::Path;
use serde::{Deserialize, Serialize};
use crate::Config;
use crate::loader::{self, LoadError};
pub const FORMAT_VERSION: u8 = 1;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Compiled {
pub format_version: u8,
pub flusso_version: String,
pub config: Config,
}
#[derive(thiserror::Error, Debug)]
pub enum CompileError {
#[error(transparent)]
Load(#[from] LoadError),
#[error("failed to read compiled config `{path}`: {source}")]
Read {
path: std::path::PathBuf,
#[source]
source: std::io::Error,
},
#[error("failed to write compiled config `{path}`: {source}")]
Write {
path: std::path::PathBuf,
#[source]
source: std::io::Error,
},
#[error("failed to encode compiled config: {0}")]
Encode(#[from] rmp_serde::encode::Error),
#[error("failed to decode compiled config: {0}")]
Decode(#[from] rmp_serde::decode::Error),
#[error(
"compiled config format version {got} is not supported by this build \
(expected {expected}); recompile with a matching `flusso`"
)]
VersionMismatch { got: u8, expected: u8 },
}
pub fn compile(config_path: impl AsRef<Path>) -> Result<Compiled, CompileError> {
let config = loader::load(config_path)?;
Ok(Compiled {
format_version: FORMAT_VERSION,
flusso_version: env!("CARGO_PKG_VERSION").to_owned(),
config,
})
}
pub fn to_bytes(compiled: &Compiled) -> Result<Vec<u8>, CompileError> {
Ok(rmp_serde::to_vec_named(compiled)?)
}
pub fn write(compiled: &Compiled, path: impl AsRef<Path>) -> Result<(), CompileError> {
let path = path.as_ref();
let bytes = to_bytes(compiled)?;
std::fs::write(path, bytes).map_err(|source| CompileError::Write {
path: path.to_path_buf(),
source,
})
}
pub fn from_bytes(bytes: &[u8]) -> Result<Config, CompileError> {
let compiled: Compiled = rmp_serde::from_slice(bytes)?;
if compiled.format_version != FORMAT_VERSION {
return Err(CompileError::VersionMismatch {
got: compiled.format_version,
expected: FORMAT_VERSION,
});
}
Ok(compiled.config)
}
pub fn load_compiled(path: impl AsRef<Path>) -> Result<Config, CompileError> {
let path = path.as_ref();
let bytes = std::fs::read(path).map_err(|source| CompileError::Read {
path: path.to_path_buf(),
source,
})?;
from_bytes(&bytes)
}