#![warn(
missing_docs,
missing_debug_implementations,
missing_copy_implementations
)]
use std::path::Path;
use snafu::ResultExt;
mod codegen;
pub mod errors;
pub use codegen::device_config_to_string;
pub use codegen::device_config_to_tokens;
use zencan_common::device_config::DeviceConfig;
use errors::*;
pub fn compile_device_config(
config_path: impl AsRef<Path>,
out_path: impl AsRef<Path>,
) -> Result<(), CompileError> {
let config = DeviceConfig::load(config_path.as_ref()).context(DeviceConfigSnafu)?;
let code = device_config_to_string(&config, true)?.to_string();
std::fs::write(out_path.as_ref(), code.as_bytes()).context(IoSnafu)?;
Ok(())
}
pub fn build_node_from_device_config(
name: &str,
config_path: impl AsRef<Path>,
) -> Result<(), CompileError> {
let output_file_path =
Path::new(&std::env::var_os("OUT_DIR").ok_or(NotRunViaCargoSnafu.build())?)
.join(format!("zencan_node_{}.rs", name));
compile_device_config(&config_path, &output_file_path)?;
let env_var = format!("ZENCAN_INCLUDE_GENERATED_{}", name);
println!("cargo:rustc-env={}={}", env_var, output_file_path.display());
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use assertables::assert_contains;
use std::io::Write;
use tempfile::NamedTempFile;
#[test]
fn test_error_display() {
let mut input_file = NamedTempFile::new().expect("Failed to create tempfile");
input_file
.write_all(
r#"
device_name = "test"
[[objects]]
"#
.as_bytes(),
)
.expect("Failed writing input file");
let out_file = NamedTempFile::new().expect("Failed to create tempfile");
let err = compile_device_config(input_file.path(), out_file.path());
assert!(err.is_err());
assert_contains!(err.unwrap_err().to_string(), "missing field `index`");
let mut input_file = NamedTempFile::new().expect("Failed to create tempfile");
input_file
.write_all(
r#"
device_name = "test"
[identity]
vendor_id = 1
product_code = 2
revision_number = 3
[[objects]]
index = 0x1
object_type = "var"
access_type = "rw"
data_type = "VisibleString(16)"
default_value = 0
"#
.as_bytes(),
)
.expect("Failed writing input file");
let out_file = NamedTempFile::new().expect("Failed to create tempfile");
let err = compile_device_config(input_file.path(), out_file.path());
assert!(err.is_err());
assert_contains!(err.unwrap_err().to_string(), "DefaultValueTypeMismatch: Default integer value 0 is not a valid value for type VisibleString(16)");
}
}