Skip to main content

codama_nodes/
node.rs

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    // Node unions.
16    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    // Nodes.
26    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}