use serde::{Deserialize, Serialize};
use crate::model::robot::Robot;
pub const MANIFEST_SCHEMA: &str = "phoxal/manifest/v0";
#[derive(phoxal_macros::DescribeWire, Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "schema", deny_unknown_fields)]
pub enum ManifestDocument {
#[serde(rename = "phoxal/manifest/v0")]
V0(Robot),
}
impl ManifestDocument {
#[must_use]
pub const fn new(robot: Robot) -> Self {
Self::V0(robot)
}
#[must_use]
pub const fn robot(&self) -> &Robot {
match self {
Self::V0(robot) => robot,
}
}
#[must_use]
pub fn into_robot(self) -> Robot {
match self {
Self::V0(robot) => robot,
}
}
}
#[cfg(test)]
mod tests {
use super::{MANIFEST_SCHEMA, ManifestDocument};
use crate::model::builder::RobotBuilder;
fn document() -> ManifestDocument {
ManifestDocument::new(
RobotBuilder::new("rover")
.component_type("rgbd", |camera| camera.camera("rgb", "lens"))
.component("front_camera", "rgbd")
.build()
.expect("a valid canonical robot"),
)
}
#[test]
fn the_schema_tag_is_written_once_on_the_wire() {
let json = serde_json::to_value(document()).expect("a manifest document serializes");
assert_eq!(json["schema"], serde_json::Value::from(MANIFEST_SCHEMA));
}
#[test]
fn a_document_round_trips_through_its_tag() {
let json = serde_json::to_value(document()).expect("a manifest document serializes");
let decoded: ManifestDocument =
serde_json::from_value(json).expect("its own output must parse");
assert_eq!(decoded.robot().id().as_str(), "rover");
assert!(decoded.robot().component("front_camera").is_some());
}
#[test]
fn an_unknown_schema_tag_is_rejected() {
let mut json = serde_json::to_value(document()).expect("a manifest document serializes");
json["schema"] = serde_json::Value::from("phoxal/manifest/v1");
assert!(serde_json::from_value::<ManifestDocument>(json).is_err());
}
}