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