Skip to main content

codama_nodes/
node.rs

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