1use crate::{
2 AccountNode, ConstantNode, ContextualValueNode, CountNode, DefinedTypeNode, DiscriminatorNode,
3 DisplayNode, ErrorNode, EventNode, HasKind, InstructionAccountNode, InstructionArgumentNode,
4 InstructionByteDeltaNode, InstructionNode, InstructionRemainingAccountsNode,
5 InstructionStatusNode, LinkNode, NodeUnionTrait, PdaNode, PdaSeedNode, PluginNode, ProgramNode,
6 ProvidedNode, RegisteredContextualValueNode, RegisteredTypeNode, RegisteredValueNode, RootNode,
7 TypeNode, ValueNode,
8};
9use derive_more::derive::From;
10use serde::{Deserialize, Serialize};
11
12#[derive(From, Debug, PartialEq, Clone, Serialize, Deserialize)]
13#[serde(untagged)]
14pub enum Node {
15 ContextualValue(RegisteredContextualValueNode),
17 Count(CountNode),
18 Discriminator(DiscriminatorNode),
19 Display(DisplayNode),
20 Link(LinkNode),
21 PdaSeed(PdaSeedNode),
22 Type(RegisteredTypeNode),
23 Value(RegisteredValueNode),
24
25 Account(AccountNode),
27 Constant(ConstantNode),
28 DefinedType(DefinedTypeNode),
29 Error(ErrorNode),
30 Event(EventNode),
31 Instruction(InstructionNode),
32 InstructionAccount(InstructionAccountNode),
33 InstructionArgument(InstructionArgumentNode),
34 InstructionByteDelta(InstructionByteDeltaNode),
35 InstructionRemainingAccounts(InstructionRemainingAccountsNode),
36 InstructionStatus(InstructionStatusNode),
37 Pda(PdaNode),
38 Plugin(PluginNode),
39 Program(ProgramNode),
40 Provided(ProvidedNode),
41 Root(RootNode),
42}
43
44impl From<ContextualValueNode> for Node {
45 fn from(node: ContextualValueNode) -> Self {
46 Node::ContextualValue(node.into())
47 }
48}
49
50impl From<TypeNode> for Node {
51 fn from(node: TypeNode) -> Self {
52 match node {
53 TypeNode::Link(link) => link.into(),
54 _ => Node::Type(node.try_into().unwrap()),
55 }
56 }
57}
58
59impl From<ValueNode> for Node {
60 fn from(node: ValueNode) -> Self {
61 Node::Value(node.into())
62 }
63}
64
65impl NodeUnionTrait for Node {}
66impl HasKind for Node {
67 fn kind(&self) -> &'static str {
68 match self {
69 Node::ContextualValue(node) => node.kind(),
70 Node::Count(node) => node.kind(),
71 Node::Discriminator(node) => node.kind(),
72 Node::Display(node) => node.kind(),
73 Node::Link(node) => node.kind(),
74 Node::PdaSeed(node) => node.kind(),
75 Node::Type(node) => node.kind(),
76 Node::Value(node) => node.kind(),
77 Node::Account(node) => node.kind(),
78 Node::Constant(node) => node.kind(),
79 Node::DefinedType(node) => node.kind(),
80 Node::Error(node) => node.kind(),
81 Node::Event(node) => node.kind(),
82 Node::Instruction(node) => node.kind(),
83 Node::InstructionAccount(node) => node.kind(),
84 Node::InstructionArgument(node) => node.kind(),
85 Node::InstructionByteDelta(node) => node.kind(),
86 Node::InstructionRemainingAccounts(node) => node.kind(),
87 Node::InstructionStatus(node) => node.kind(),
88 Node::Pda(node) => node.kind(),
89 Node::Plugin(node) => node.kind(),
90 Node::Program(node) => node.kind(),
91 Node::Provided(node) => node.kind(),
92 Node::Root(node) => node.kind(),
93 }
94 }
95}
96
97impl HasKind for Option<Node> {
98 fn kind(&self) -> &'static str {
99 match self {
100 Some(node) => node.kind(),
101 None => "None",
102 }
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109 use crate::{NumberTypeNode, NumberValueNode, U32};
110
111 #[test]
112 fn kind() {
113 let node: Node = ProgramNode::default().into();
114 assert_eq!(node.kind(), "programNode");
115 }
116
117 #[test]
118 fn type_node_to_json() {
119 let node: Node = NumberTypeNode::le(U32).into();
120 let json = serde_json::to_string(&node).unwrap();
121 assert_eq!(
122 json,
123 r#"{"kind":"numberTypeNode","format":"u32","endian":"le"}"#
124 );
125 }
126
127 #[test]
128 fn type_node_from_json() {
129 let json = r#"{"kind":"numberTypeNode","format":"u32","endian":"le"}"#;
130 let node: Node = serde_json::from_str(json).unwrap();
131 assert_eq!(
132 node,
133 Node::Type(RegisteredTypeNode::Number(NumberTypeNode::le(U32)))
134 );
135 }
136
137 #[test]
138 fn defined_type_to_json() {
139 let node: Node = DefinedTypeNode::new("myType", NumberTypeNode::le(U32)).into();
140 let json = serde_json::to_string(&node).unwrap();
141 assert_eq!(
142 json,
143 r#"{"kind":"definedTypeNode","name":"myType","type":{"kind":"numberTypeNode","format":"u32","endian":"le"}}"#
144 );
145 }
146
147 #[test]
148 fn defined_type_from_json() {
149 let json = r#"{"kind":"definedTypeNode","name":"myType","type":{"kind":"numberTypeNode","format":"u32","endian":"le"}}"#;
150 let node: Node = serde_json::from_str(json).unwrap();
151 assert_eq!(
152 node,
153 Node::DefinedType(DefinedTypeNode::new("myType", NumberTypeNode::le(U32)))
154 );
155 }
156
157 #[test]
158 fn constant_to_json() {
159 let node: Node = ConstantNode::new(
160 "myConstant",
161 NumberTypeNode::le(U32),
162 NumberValueNode::new(42u32),
163 )
164 .into();
165 let json = serde_json::to_string(&node).unwrap();
166 assert_eq!(
167 json,
168 r#"{"kind":"constantNode","name":"myConstant","type":{"kind":"numberTypeNode","format":"u32","endian":"le"},"value":{"kind":"numberValueNode","number":42}}"#
169 );
170 }
171
172 #[test]
173 fn constant_from_json() {
174 let json = r#"{"kind":"constantNode","name":"myConstant","type":{"kind":"numberTypeNode","format":"u32","endian":"le"},"value":{"kind":"numberValueNode","number":42}}"#;
175 let node: Node = serde_json::from_str(json).unwrap();
176 assert_eq!(
177 node,
178 Node::Constant(ConstantNode::new(
179 "myConstant",
180 NumberTypeNode::le(U32),
181 NumberValueNode::new(42u32)
182 ))
183 );
184 }
185}