use serde::Deserialize; #[derive(Debug, Clone, Deserialize)] pub struct Level { id: String, sort_order: i32, name: String, description: String, #[serde(default)] init_board: Option, /// no stages means sandbox #[serde(default)] stages: Vec, } #[derive(Debug, Clone, Deserialize)] pub struct Stage { input: IOData, output: IOData, } #[derive(Debug, Clone, Deserialize)] #[serde(untagged)] pub enum IOData { Bytes(Vec), Text(String), } impl IOData { pub fn as_bytes(&self) -> &[u8] { match self { IOData::Bytes(b) => b, IOData::Text(t) => t.as_bytes(), } } pub fn is_text(&self) -> bool { matches!(self, IOData::Text(_)) } } impl Level { pub fn id(&self) -> &str { &self.id } pub fn sort_order(&self) -> i32 { self.sort_order } pub fn name(&self) -> &str { &self.name } pub fn description(&self) -> &str { &self.description } pub fn is_sandbox(&self) -> bool { self.stages.is_empty() } pub fn init_board(&self) -> Option { self.init_board.clone() } pub fn stages(&self) -> &[Stage] { &self.stages } } impl Stage { pub fn input(&self) -> &IOData { &self.input } pub fn output(&self) -> &IOData { &self.output } }