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 Ok(ArgumentDirective {
26 after: consumer.after.option().unwrap_or(false),
27 argument: InstructionArgumentNode {
28 name: consumer.name.take(meta)?,
29 r#type: consumer.r#type.take(meta)?,
30 docs: Docs::default(),
31 default_value: consumer.argument_default_value.option(),
32 default_value_strategy: consumer.default_value_strategy.option(),
33 },
34 })
35 }
36}
37
38impl<'a> TryFrom<&'a CodamaAttribute<'a>> for &'a ArgumentDirective {
39 type Error = CodamaError;
40
41 fn try_from(attribute: &'a CodamaAttribute) -> Result<Self, Self::Error> {
42 match attribute.directive {
43 CodamaDirective::Argument(ref a) => Ok(a),
44 _ => Err(CodamaError::InvalidCodamaDirective {
45 expected: "argument".to_string(),
46 actual: attribute.directive.name().to_string(),
47 }),
48 }
49 }
50}
51
52impl<'a> TryFrom<&'a Attribute<'a>> for &'a ArgumentDirective {
53 type Error = CodamaError;
54
55 fn try_from(attribute: &'a Attribute) -> Result<Self, Self::Error> {
56 <&CodamaAttribute>::try_from(attribute)?.try_into()
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63 use codama_nodes::{NumberFormat::U8, NumberTypeNode, PayerValueNode};
64
65 #[test]
66 fn ok() {
67 let meta: Meta = syn::parse_quote! { argument("age", number(u8)) };
68 let directive = ArgumentDirective::parse(&meta).unwrap();
69 assert_eq!(
70 directive,
71 ArgumentDirective {
72 after: false,
73 argument: InstructionArgumentNode::new("age", NumberTypeNode::le(U8)),
74 }
75 );
76 }
77
78 #[test]
79 fn after() {
80 let meta: Meta = syn::parse_quote! { argument(after, "age", number(u8)) };
81 let directive = ArgumentDirective::parse(&meta).unwrap();
82 assert_eq!(
83 directive,
84 ArgumentDirective {
85 after: true,
86 argument: InstructionArgumentNode::new("age", NumberTypeNode::le(U8)),
87 }
88 );
89 }
90
91 #[test]
92 fn with_default_value() {
93 let meta: Meta = syn::parse_quote! { argument("age", number(u8), default_value = payer) };
94 let directive = ArgumentDirective::parse(&meta).unwrap();
95 assert_eq!(
96 directive,
97 ArgumentDirective {
98 after: false,
99 argument: InstructionArgumentNode {
100 default_value: Some(PayerValueNode::new().into()),
101 ..InstructionArgumentNode::new("age", NumberTypeNode::le(U8))
102 },
103 }
104 );
105 }
106}