use std::fs;
use std::path::Path;
use crate::Error;
use crate::formats;
use crate::formats::slice_summary::SliceSummary;
use crate::model::filament::MaterialProfile;
use crate::model::job::{Job, JobSource};
use crate::model::printer::PrinterProfile;
impl Job {
pub fn slice_summary(&self) -> Result<SliceSummary, Error> {
match &self.source {
JobSource::Embedded(summary) => Ok(summary.clone()),
JobSource::Path(path) => {
if cfg!(all(target_family = "wasm", not(target_os = "wasi"))) {
return Err(Error::DiskUnavailable);
}
read_slice_file(path)
}
}
}
}
pub fn read_slice_file(path: &Path) -> Result<SliceSummary, Error> {
let bytes = fs::read(path)?;
let filename = path.file_name().and_then(|f| f.to_str()).unwrap_or("");
Ok(formats::parse_slice_bytes(&bytes, filename)?)
}
pub fn read_job(path: &Path) -> Result<Job, Error> {
crate::parse_job(&fs::read_to_string(path)?)
}
pub fn read_printer(path: &Path) -> Result<PrinterProfile, Error> {
crate::parse_printer(&fs::read_to_string(path)?)
}
pub fn read_material(path: &Path) -> Result<MaterialProfile, Error> {
crate::parse_material(&fs::read_to_string(path)?)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::model::filament::MaterialKind;
use crate::model::printer::PrinterKind;
#[test]
fn read_slice_file_parses_fixture() {
let path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../Testfiles/Shape-Box.sl1");
let summary = read_slice_file(&path).unwrap();
assert_eq!(summary.plates.len(), 1);
assert!(summary.plates[0].print_time_seconds > 0.0);
}
fn remove_dir_if_present(path: &Path) {
match fs::remove_dir_all(path) {
Ok(()) => {}
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {}
Err(e) => panic!("couldn't remove {}: {e}", path.display()),
}
}
#[test]
fn read_profiles_and_job_from_disk() {
let dir = std::env::temp_dir().join("printcalc-test-disk");
remove_dir_if_present(&dir);
fs::create_dir_all(&dir).unwrap();
let printer_path = dir.join("printer.toml");
fs::write(
&printer_path,
r#"
name = "test-printer"
kind = "fdm"
purchase_price = 500.0
additional_upfront_cost = 0.0
estimated_life_years = 5.0
estimated_uptime_percent = 0.5
annual_maintenance_cost = 50.0
power_consumption_watts = 150.0
cost_buffer_factor = 1.2
"#,
)
.unwrap();
let printer = read_printer(&printer_path).unwrap();
assert_eq!(printer.name, "test-printer");
assert_eq!(printer.kind, PrinterKind::Fdm);
let material_path = dir.join("filament.toml");
fs::write(
&material_path,
r#"
name = "test-pla"
kind = "filament"
price = 20.0
efficiency_factor = 1.1
"#,
)
.unwrap();
let material = read_material(&material_path).unwrap();
assert_eq!(material.kind, MaterialKind::Filament);
assert!(matches!(
read_job(&dir.join("nope.toml")).unwrap_err(),
Error::Io(_)
));
remove_dir_if_present(&dir);
}
#[test]
fn job_slice_summary_handles_both_source_kinds() {
let path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../Testfiles/Shape-Box.sl1");
let from_path = crate::new_job(
"widget",
path,
crate::create_printer(
"sl1-printer",
PrinterKind::Resin,
crate::WearProfile {
purchase_price: 400.0,
additional_upfront_cost: 0.0,
estimated_life_years: 5.0,
estimated_uptime_percent: 0.3,
annual_maintenance_cost: 20.0,
power_consumption_watts: 60.0,
cost_buffer_factor: 1.2,
print_time_rate_override: None,
},
),
std::collections::HashMap::new(),
None,
Vec::new(),
);
let summary = from_path.slice_summary().unwrap();
assert_eq!(summary.plates.len(), 1);
let embedded = Job {
source: JobSource::Embedded(summary.clone()),
..from_path
};
assert_eq!(embedded.slice_summary().unwrap(), summary);
}
}