codama_attributes/codama_directives/
argument_directive.rs1use crate::{
2 codama_directives::type_nodes::StructFieldMetaConsumer,
3 utils::{FromMeta, MetaConsumer},
4 Attribute, CodamaAttribute, CodamaDirective,
5};
6use codama_errors::CodamaError;
7use codama_nodes::{Docs, InstructionArgumentNode};
8use codama_syn_helpers::Meta;
9
10#[derive(Debug, PartialEq)]
11pub struct ArgumentDirective {
12 pub after: bool,
13 pub argument: InstructionArgumentNode,
14}
15
16impl ArgumentDirective {
17 pub fn parse(meta: &Meta) -> syn::Result<Self> {
18 meta.assert_directive("argument")?;
19 let consumer = StructFieldMetaConsumer::from_meta(meta)?
20 .consume_field()?
21 .consume_argument_default_value()?
22 .consume_after()?
23 .assert_fully_consumed()?;
24
25 let default_value = consumer.default_instruction_input_value_node();
26 let default_value_strategy = consumer.default_value_strategy();
27
28 Ok(ArgumentDirective {
29 after: consumer.after.option().unwrap_or(false),
30 argument: InstructionArgumentNode {
31 name: consumer.name.take(meta)?,
32 r#type: consumer.r#type.take(meta)?,
33 docs: Docs::default(),
34 default_value,
35 default_value_strategy,
36 },
37 })
38 }
39}
40
41impl<'a> TryFrom<&'a CodamaAttribute<'a>> for &'a ArgumentDirective {
42 type Error = CodamaError;
43
44 fn try_from(attribute: &'a CodamaAttribute) -> Result<Self, Self::Error> {
45 match attribute.directive {
46 CodamaDirective::Argument(ref a) => Ok(a),
47 _ => Err(CodamaError::InvalidCodamaDirective {
48 expected: "argument".to_string(),
49 actual: attribute.directive.name().to_string(),
50 }),
51 }
52 }
53}
54
55impl<'a> TryFrom<&'a Attribute<'a>> for &'a ArgumentDirective {
56 type Error = CodamaError;
57
58 fn try_from(attribute: &'a Attribute) -> Result<Self, Self::Error> {
59 <&CodamaAttribute>::try_from(attribute)?.try_into()
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66 use codama_nodes::{NumberFormat::U8, NumberTypeNode, PayerValueNode};
67
68 #[test]
69 fn ok() {
70 let meta: Meta = syn::parse_quote! { argument("age", number(u8)) };
71 let directive = ArgumentDirective::parse(&meta).unwrap();
72 assert_eq!(
73 directive,
74 ArgumentDirective {
75 after: false,
76 argument: InstructionArgumentNode::new("age", NumberTypeNode::le(U8)),
77 }
78 );
79 }
80
81 #[test]
82 fn after() {
83 let meta: Meta = syn::parse_quote! { argument(after, "age", number(u8)) };
84 let directive = ArgumentDirective::parse(&meta).unwrap();
85 assert_eq!(
86 directive,
87 ArgumentDirective {
88 after: true,
89 argument: InstructionArgumentNode::new("age", NumberTypeNode::le(U8)),
90 }
91 );
92 }
93
94 #[test]
95 fn with_default_value() {
96 let meta: Meta = syn::parse_quote! { argument("age", number(u8), default_value = payer) };
97 let directive = ArgumentDirective::parse(&meta).unwrap();
98 assert_eq!(
99 directive,
100 ArgumentDirective {
101 after: false,
102 argument: InstructionArgumentNode {
103 default_value: Some(PayerValueNode::new().into()),
104 ..InstructionArgumentNode::new("age", NumberTypeNode::le(U8))
105 },
106 }
107 );
108 }
109}