use serde::{Deserialize, Serialize}; use crate::ids::SurfaceId; /// Split orientation. `H` lays children left-to-right; `V` top-to-bottom. #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum Orient { H, V, } /// Recursive n-ary layout tree. Externally tagged so JSON reads /// `{ "leaf": { "surface_id": "s_1" } }` / `{ "split": { ... } }`. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum LayoutNode { Leaf { surface_id: SurfaceId }, Split { orient: Orient, ratios: Vec, children: Vec, }, } impl LayoutNode { pub fn leaf(id: SurfaceId) -> Self { LayoutNode::Leaf { surface_id: id } } } #[cfg(test)] mod tests { use super::*; #[test] fn leaf_serializes_externally_tagged() { let n = LayoutNode::leaf(SurfaceId("s_1".into())); let j = serde_json::to_string(&n).unwrap(); assert_eq!(j, r#"{"leaf":{"surface_id":"s_1"}}"#); } #[test] fn split_round_trips() { let n = LayoutNode::Split { orient: Orient::V, ratios: vec![0.5, 0.5], children: vec![ LayoutNode::leaf(SurfaceId("s_1".into())), LayoutNode::leaf(SurfaceId("s_2".into())), ], }; let j = serde_json::to_string(&n).unwrap(); assert!(j.contains(r#""split""#)); assert!(j.contains(r#""orient":"v""#)); let back: LayoutNode = serde_json::from_str(&j).unwrap(); assert_eq!(back, n); } }