use derive_builder::Builder;
use indexmap::IndexSet;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Builder, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct State {
#[builder(setter(into))]
pub(crate) id: String,
#[builder(setter(into))]
#[serde(rename = "desc")]
pub(crate) description: String,
#[builder(setter(into))]
#[serde(rename = "default")]
initial: String,
#[serde(flatten)]
pub(crate) kind: StateType,
#[builder(setter(into, strip_option), default)]
#[serde(skip_serializing_if = "Option::is_none")]
parent_group: Option<String>,
}
impl State {
pub fn builder() -> StateBuilder {
StateBuilder::default()
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[non_exhaustive]
#[serde(rename_all = "lowercase")]
#[serde(tag = "type")]
pub enum StateType {
Choice(ChoiceState),
Text(TextState),
}
#[derive(Debug, Clone, Builder, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ChoiceState {
#[builder(setter(each(name = "choice", into)))]
#[serde(rename = "valueChoices")]
pub(crate) choices: IndexSet<String>,
}
impl ChoiceState {
pub fn builder() -> ChoiceStateBuilder {
ChoiceStateBuilder::default()
}
}
#[derive(Debug, Clone, Builder, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TextState {}
impl TextState {
pub fn builder() -> TextStateBuilder {
TextStateBuilder::default()
}
}
#[test]
fn serialize_example_state() {
assert_eq!(
serde_json::to_value(
State::builder()
.id("tp_sid_fruit")
.description("Fruit Kind description")
.initial("Apple")
.parent_group("Fruits")
.kind(StateType::Choice(
ChoiceState::builder()
.choice("Apple")
.choice("Pears")
.choice("Grapes")
.choice("Bananas")
.build()
.unwrap()
))
.build()
.unwrap()
)
.unwrap(),
serde_json::json! {{
"id":"tp_sid_fruit",
"type":"choice",
"desc":"Fruit Kind description",
"default":"Apple",
"parentGroup":"Fruits",
"valueChoices": [
"Apple",
"Pears",
"Grapes",
"Bananas"
]
}}
);
}