use serde::{Deserialize, Serialize};
use crate::OptionKind;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ElementClass {
Point,
Polyline,
Region,
Collection,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ElementRole {
Conveyance,
Boundary,
Control,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ElementKind {
pub id: &'static str,
pub label: &'static str,
pub label_plural: &'static str,
pub class: ElementClass,
pub role: Option<ElementRole>,
pub badge: &'static str,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub group: Option<&'static str>,
pub creatable: bool,
pub not_creatable_because: Option<&'static str>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AttributeDescriptor {
pub key: String,
pub label: String,
pub kind: OptionKind,
pub quantity: Option<String>,
#[serde(default)]
pub editable: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub references: Vec<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn element_class_serialises_lowercase() {
assert_eq!(
serde_json::to_string(&ElementClass::Region).unwrap(),
"\"region\""
);
assert_eq!(
serde_json::to_string(&ElementClass::Collection).unwrap(),
"\"collection\""
);
}
#[test]
fn a_kind_in_no_group_carries_no_group_field() {
let kind = ElementKind {
id: "k",
label: "Kind",
label_plural: "Kinds",
class: ElementClass::Collection,
role: None,
badge: "K",
group: None,
creatable: false,
not_creatable_because: None,
};
let json = serde_json::to_value(kind).unwrap();
assert!(json.get("group").is_none(), "{json}");
}
#[test]
fn kind_descriptor_serialises_camel_case() {
let kind = ElementKind {
id: "k",
label: "Kind",
label_plural: "Kinds",
class: ElementClass::Point,
role: Some(ElementRole::Boundary),
badge: "K",
group: Some("Kinds"),
creatable: false,
not_creatable_because: Some("a kind needs something only its engine knows"),
};
let json = serde_json::to_value(kind).unwrap();
assert_eq!(json["labelPlural"], "Kinds");
assert_eq!(json["class"], "point");
assert_eq!(json["role"], "boundary");
assert_eq!(json["creatable"], false);
assert_eq!(json["group"], "Kinds");
assert_eq!(
json["notCreatableBecause"],
"a kind needs something only its engine knows"
);
}
#[test]
fn an_attribute_without_the_flag_is_not_editable() {
let json = serde_json::json!({
"key": "elevation",
"label": "Elevation",
"kind": { "type": "number" },
"quantity": "elevation",
});
let attr: AttributeDescriptor =
serde_json::from_value(json).expect("a pre-contract schema still reads");
assert!(!attr.editable);
}
}