From 10e7f7763a5bae00a9f30929dbbc9aaf084b57a0 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 04:13:55 -0500 Subject: [PATCH] Test typed StencilCraft document readers --- crates/stencilcraft-format/src/lib.rs | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/crates/stencilcraft-format/src/lib.rs b/crates/stencilcraft-format/src/lib.rs index 9a0df0093..1ff64af59 100644 --- a/crates/stencilcraft-format/src/lib.rs +++ b/crates/stencilcraft-format/src/lib.rs @@ -364,6 +364,7 @@ pub enum Error { mod tests { use std::io::{self, Cursor, Read}; + use serde::{Deserialize, Serialize}; use serde_json::{Value, json}; use super::{DocumentFields, Error, FORMAT_VERSION, File}; @@ -469,4 +470,43 @@ mod tests { assert!(matches!(File::read("{"), Err(Error::Json(_)))); assert!(matches!(File::read(r#"{"stencilcraft":{"name":"stencilcraft","version":1}}"#), Err(Error::Document { .. }))); } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct TypedBoard { + width_mm: f64, + height_mm: f64, + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct TypedFields { + board: TypedBoard, + #[serde(default, rename = "board-setup", skip_serializing_if = "Option::is_none")] + board_setup: Option, + } + + fn typed_fields() -> TypedFields { + TypedFields { board: TypedBoard { width_mm: 100.0, height_mm: 150.0 }, board_setup: None } + } + + #[test] + fn typed_readers_round_trip_typed_fields_and_preserve_header_errors() -> Result<(), Error> { + let file = File::new(typed_fields()); + let text = file.to_json_pretty()?; + assert!(!text.contains("board-setup")); + assert_eq!(File::read_typed(&text)?, file); + assert_eq!(File::read_typed_from(Cursor::new(text.as_bytes()))?, file); + + let malformed = r#"{"stencilcraft":{"name":"stencilcraft","version":1},"board":"wrong"}"#; + assert!(matches!(File::::read_typed(malformed), Err(Error::Document { .. }))); + assert!(matches!(File::::read_typed_from(Cursor::new(malformed)), Err(Error::Document { .. }))); + + let wrong_header = r#"{"stencilcraft":{"name":"other","version":1},"board":{}}"#; + assert!(matches!(File::::read_typed(wrong_header), Err(Error::NotStencilCraft))); + assert!(matches!(File::::read_typed_from(Cursor::new(wrong_header)), Err(Error::NotStencilCraft))); + + let future_version = r#"{"stencilcraft":{"name":"stencilcraft","version":2},"board":{}}"#; + assert!(matches!(File::::read_typed(future_version), Err(Error::Version { found: 2, supported: 1 }))); + assert!(matches!(File::::read_typed_from(Cursor::new(future_version)), Err(Error::Version { found: 2, supported: 1 }))); + Ok(()) + } }