codama_nodes/value_nodes/
enum_value_node.rs1use crate::{CamelCaseString, DefinedTypeLinkNode, StructValueNode, TupleValueNode};
2use codama_nodes_derive::{node, node_union};
3
4#[node]
5pub struct EnumValueNode {
6 pub variant: CamelCaseString,
8
9 pub r#enum: DefinedTypeLinkNode,
11 #[serde(skip_serializing_if = "crate::is_default")]
12 pub value: Option<EnumVariantData>,
13}
14
15impl From<EnumValueNode> for crate::Node {
16 fn from(val: EnumValueNode) -> Self {
17 crate::Node::Value(val.into())
18 }
19}
20
21impl EnumValueNode {
22 pub fn new<T, U>(r#enum: T, variant: U, value: Option<EnumVariantData>) -> Self
23 where
24 T: Into<DefinedTypeLinkNode>,
25 U: Into<CamelCaseString>,
26 {
27 Self {
28 variant: variant.into(),
29 r#enum: r#enum.into(),
30 value,
31 }
32 }
33
34 pub fn empty<T, U>(r#enum: T, variant: U) -> Self
35 where
36 T: Into<DefinedTypeLinkNode>,
37 U: Into<CamelCaseString>,
38 {
39 Self {
40 variant: variant.into(),
41 r#enum: r#enum.into(),
42 value: None,
43 }
44 }
45
46 pub fn fields<T, U, V>(r#enum: T, variant: U, value: V) -> Self
47 where
48 T: Into<DefinedTypeLinkNode>,
49 U: Into<CamelCaseString>,
50 V: Into<StructValueNode>,
51 {
52 Self {
53 variant: variant.into(),
54 r#enum: r#enum.into(),
55 value: Some(EnumVariantData::Struct(value.into())),
56 }
57 }
58
59 pub fn tuple<T, U, V>(r#enum: T, variant: U, value: V) -> Self
60 where
61 T: Into<DefinedTypeLinkNode>,
62 U: Into<CamelCaseString>,
63 V: Into<TupleValueNode>,
64 {
65 Self {
66 variant: variant.into(),
67 r#enum: r#enum.into(),
68 value: Some(EnumVariantData::Tuple(value.into())),
69 }
70 }
71}
72
73#[node_union]
74pub enum EnumVariantData {
75 Struct(StructValueNode),
76 Tuple(TupleValueNode),
77}
78
79#[cfg(test)]
80mod tests {
81 use crate::{NumberValueNode, StringValueNode, StructFieldValueNode};
82
83 use super::*;
84
85 #[test]
86 fn new() {
87 let node = EnumValueNode::new("direction", "north", None);
88 assert_eq!(node.r#enum, DefinedTypeLinkNode::new("direction"));
89 assert_eq!(node.variant, CamelCaseString::from("north"));
90 assert_eq!(node.value, None);
91 }
92
93 #[test]
94 fn empty() {
95 let node = EnumValueNode::empty("command", "exit");
96 assert_eq!(node.r#enum, DefinedTypeLinkNode::new("command"));
97 assert_eq!(node.variant, CamelCaseString::from("exit"));
98 assert_eq!(node.value, None);
99 }
100
101 #[test]
102 fn fields() {
103 let node = EnumValueNode::fields(
104 "command",
105 "move",
106 vec![
107 StructFieldValueNode::new("x", NumberValueNode::new(10)),
108 StructFieldValueNode::new("y", NumberValueNode::new(20)),
109 ],
110 );
111 assert_eq!(node.r#enum, DefinedTypeLinkNode::new("command"));
112 assert_eq!(node.variant, CamelCaseString::from("move"));
113 assert_eq!(
114 node.value,
115 Some(EnumVariantData::Struct(StructValueNode::new(vec![
116 StructFieldValueNode::new("x", NumberValueNode::new(10)),
117 StructFieldValueNode::new("y", NumberValueNode::new(20)),
118 ])))
119 );
120 }
121
122 #[test]
123 fn tuple() {
124 let node = EnumValueNode::tuple(
125 "command",
126 "write",
127 vec![StringValueNode::new("Hello World").into()],
128 );
129 assert_eq!(node.r#enum, DefinedTypeLinkNode::new("command"));
130 assert_eq!(node.variant, CamelCaseString::from("write"));
131 assert_eq!(
132 node.value,
133 Some(EnumVariantData::Tuple(TupleValueNode::new(vec![
134 StringValueNode::new("Hello World").into()
135 ])))
136 );
137 }
138
139 #[test]
140 fn to_json() {
141 let node = EnumValueNode::empty("command", "exit");
142 let json = serde_json::to_string(&node).unwrap();
143 assert_eq!(
144 json,
145 r#"{"kind":"enumValueNode","variant":"exit","enum":{"kind":"definedTypeLinkNode","name":"command"}}"#
146 );
147 }
148
149 #[test]
150 fn from_json() {
151 let json = r#"{"kind":"enumValueNode","variant":"exit","enum":{"kind":"definedTypeLinkNode","name":"command"}}"#;
152 let node: EnumValueNode = serde_json::from_str(json).unwrap();
153 assert_eq!(node, EnumValueNode::empty("command", "exit"));
154 }
155}