use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
pub const REQUIRED_META_FIELDS: [&str; 10] = [
"meta_version",
"normal_exposure_ms",
"bottom_exposure_ms",
"bottom_layer_count",
"transition_layer_count",
"layer_height_um",
"lift_slow_distance_um",
"lift_slow_speed_um_min",
"retract_fast_distance_um",
"retract_fast_speed_um_min",
];
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct Timing {
#[serde(skip_serializing_if = "Option::is_none", default)]
pub layer_height_um: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub normal_exposure_ms: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottom_exposure_ms: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottom_layer_count: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub transition_layer_count: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub lift_slow_distance_um: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub lift_slow_speed_um_min: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub lift_fast_distance_um: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub lift_fast_speed_um_min: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub retract_fast_distance_um: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub retract_fast_speed_um_min: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub retract_slow_distance_um: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub retract_slow_speed_um_min: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottom_lift_slow_distance_um: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottom_lift_slow_speed_um_min: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottom_lift_fast_distance_um: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottom_lift_fast_speed_um_min: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottom_retract_fast_distance_um: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottom_retract_fast_speed_um_min: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottom_retract_slow_distance_um: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottom_retract_slow_speed_um_min: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub wait_time_before_cure_ms: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub wait_time_after_cure_ms: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub wait_time_after_lift_ms: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottom_wait_time_before_cure_ms: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottom_wait_time_after_cure_ms: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottom_wait_time_after_lift_ms: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub light_pwm: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottom_light_pwm: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub chamber_temperature_c: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub vat_temperature_c: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub cure_curve: Option<CureCurve>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
impl Timing {
pub fn vendor_extra(&self) -> Option<&Value> {
self.extra.get("extra")
}
pub fn field_names() -> &'static [&'static str] {
&[
"layer_height_um",
"normal_exposure_ms",
"bottom_exposure_ms",
"bottom_layer_count",
"transition_layer_count",
"lift_slow_distance_um",
"lift_slow_speed_um_min",
"lift_fast_distance_um",
"lift_fast_speed_um_min",
"retract_fast_distance_um",
"retract_fast_speed_um_min",
"retract_slow_distance_um",
"retract_slow_speed_um_min",
"bottom_lift_slow_distance_um",
"bottom_lift_slow_speed_um_min",
"bottom_lift_fast_distance_um",
"bottom_lift_fast_speed_um_min",
"bottom_retract_fast_distance_um",
"bottom_retract_fast_speed_um_min",
"bottom_retract_slow_distance_um",
"bottom_retract_slow_speed_um_min",
"wait_time_before_cure_ms",
"wait_time_after_cure_ms",
"wait_time_after_lift_ms",
"bottom_wait_time_before_cure_ms",
"bottom_wait_time_after_cure_ms",
"bottom_wait_time_after_lift_ms",
"light_pwm",
"bottom_light_pwm",
"chamber_temperature_c",
"vat_temperature_c",
"cure_curve",
]
}
pub fn missing_from(object: &Map<String, Value>, names: &[&str]) -> Vec<String> {
names
.iter()
.filter(|name| !object.contains_key(**name))
.map(|name| (*name).to_string())
.collect()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct CureCurve {
pub dp_um: f64,
pub ec_mj_cm2: f64,
pub e0_mj_cm2: f64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Material {
#[serde(default)]
pub name: String,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub brand: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub family: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub density_g_ml: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub color_rgba: Option<[u8; 4]>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottle_price: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bottle_capacity_ml: Option<f64>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct Printer {
#[serde(skip_serializing_if = "Option::is_none", default)]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub manufacturer: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub firmware_version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub serial: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub display_width_px: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub display_height_px: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub pixel_size_um: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub build_width_um: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub build_depth_um: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub build_height_um: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub bit_depth: Option<u32>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct CompatiblePrinter {
#[serde(skip_serializing_if = "Option::is_none", default)]
pub manufacturer: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub model_pattern: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub display_width_px: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub display_height_px: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub pixel_size_um: Option<u32>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct AntiAliasing {
#[serde(skip_serializing_if = "Option::is_none", default)]
pub enabled: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub level: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub mode: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub minimum_alpha_percent: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub blur_brush_radius_px: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub blur_brush_kernel: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub blur_brush_sigma_x: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub blur_brush_sigma_y: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub z_blend_look_back: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub z_blend_fade_px: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub dither_enabled: Option<bool>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
pub struct ScaleCompensation {
#[serde(default)]
pub x: f64,
#[serde(default)]
pub y: f64,
#[serde(default)]
pub z: f64,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct Slicer {
#[serde(skip_serializing_if = "Option::is_none", default)]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub url: Option<String>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct Meta {
#[serde(skip_serializing_if = "Option::is_none", default)]
pub meta_version: Option<u32>,
#[serde(flatten)]
pub timing: Timing,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub materials: Option<Vec<Material>>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub sectors: Option<Vec<Sector>>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub printer: Option<Printer>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub anti_aliasing: Option<AntiAliasing>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub scale_compensation_pct: Option<ScaleCompensation>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub estimated_print_time_sec: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub estimated_resin_volume_ml: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub slicer: Option<Slicer>,
}
impl Meta {
pub fn extra(&self) -> Option<&Value> {
self.timing.vendor_extra()
}
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct Profile {
#[serde(default)]
pub profile_name: String,
#[serde(default)]
pub profile_version: String,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub profile_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub profile_uuid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub author: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub created_unix_sec: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub compatible_printers: Option<Vec<CompatiblePrinter>>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub printer: Option<Printer>,
#[serde(default)]
pub settings: Timing,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub anti_aliasing: Option<AntiAliasing>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub materials: Option<Vec<Material>>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub scale_compensation_pct: Option<ScaleCompensation>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub extra: Option<Value>,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct Sector {
#[serde(default)]
pub sector_id: u32,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub material_index: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub color_rgba: Option<[u8; 4]>,
#[serde(flatten)]
pub timing: Timing,
}