Skip to main content

codama_nodes/
instruction_argument_node.rs

1use crate::{
2    CamelCaseString, Docs, InstructionArgumentNode, InstructionInputValueNode, StructFieldTypeNode,
3    StructTypeNode, TypeNode,
4};
5
6impl InstructionArgumentNode {
7    pub fn new<T, U>(name: T, r#type: U) -> Self
8    where
9        T: Into<CamelCaseString>,
10        U: Into<TypeNode>,
11    {
12        Self {
13            name: name.into(),
14            default_value_strategy: None,
15            docs: Docs::default(),
16            r#type: Box::new(r#type.into()),
17            default_value: Box::new(None),
18        }
19    }
20}
21
22impl From<StructFieldTypeNode> for InstructionArgumentNode {
23    fn from(value: StructFieldTypeNode) -> Self {
24        Self {
25            name: value.name,
26            default_value_strategy: value.default_value_strategy,
27            docs: value.docs,
28            // `StructFieldTypeNode.r#type` is `Box<TypeNode>`;
29            // `InstructionArgumentNode.r#type` is also `Box<TypeNode>`,
30            // so forward the existing box.
31            r#type: value.r#type,
32            default_value: Box::new((*value.default_value).map(InstructionInputValueNode::from)),
33        }
34    }
35}
36
37impl From<StructTypeNode> for Vec<InstructionArgumentNode> {
38    fn from(val: StructTypeNode) -> Self {
39        val.fields
40            .into_iter()
41            .map(InstructionArgumentNode::from)
42            .collect()
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49    use crate::{ArgumentValueNode, DefaultValueStrategy, NumberTypeNode, U32};
50
51    #[test]
52    fn new() {
53        let node = InstructionArgumentNode::new("my_argument", NumberTypeNode::le(U32));
54        assert_eq!(node.name, CamelCaseString::new("myArgument"));
55        assert_eq!(*node.r#type, TypeNode::Number(NumberTypeNode::le(U32)));
56    }
57
58    #[test]
59    fn direct_instantiation() {
60        let node = InstructionArgumentNode {
61            name: "myArgument".into(),
62            default_value_strategy: Some(DefaultValueStrategy::Optional),
63            docs: vec!["Hello".to_string()].into(),
64            r#type: Box::new(NumberTypeNode::le(U32).into()),
65            default_value: Box::new(Some(ArgumentValueNode::new("myOtherArgument").into())),
66        };
67
68        assert_eq!(node.name, CamelCaseString::new("myArgument"));
69        assert_eq!(
70            node.default_value_strategy,
71            Some(DefaultValueStrategy::Optional)
72        );
73        assert_eq!(*node.docs, vec!["Hello".to_string()]);
74        assert_eq!(*node.r#type, TypeNode::Number(NumberTypeNode::le(U32)));
75        assert_eq!(
76            *node.default_value,
77            Some(InstructionInputValueNode::ArgumentValue(
78                ArgumentValueNode::new("myOtherArgument")
79            ))
80        );
81    }
82
83    #[test]
84    fn to_json() {
85        let node = InstructionArgumentNode::new("myArgument", NumberTypeNode::le(U32));
86        let json = serde_json::to_string(&node).unwrap();
87        assert_eq!(
88            json,
89            r#"{"kind":"instructionArgumentNode","name":"myArgument","type":{"kind":"numberTypeNode","format":"u32","endian":"le"}}"#
90        );
91    }
92
93    #[test]
94    fn from_json() {
95        let json = r#"{"kind":"instructionArgumentNode","name":"myArgument","type":{"kind":"numberTypeNode","format":"u32","endian":"le"}}"#;
96        let node: InstructionArgumentNode = serde_json::from_str(json).unwrap();
97        assert_eq!(
98            node,
99            InstructionArgumentNode::new("myArgument", NumberTypeNode::le(U32))
100        );
101    }
102}