1use super::*;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4#[non_exhaustive]
5pub enum RdMethodKind {
6 Method,
7 S3Method,
8 S4Method,
9}
10
11#[derive(Debug, Clone, PartialEq)]
12pub struct RdMethod<'a> {
16 path: RdPath,
17 kind: RdMethodKind,
18 generic_nodes: &'a [RdNode],
19 generic: String,
20 qualifier_nodes: &'a [RdNode],
21 qualifier: String,
22}
23
24impl<'a> RdMethod<'a> {
25 pub fn path(&self) -> &RdPath {
26 &self.path
27 }
28 pub fn kind(&self) -> RdMethodKind {
29 self.kind
30 }
31 pub fn generic_nodes(&self) -> &'a [RdNode] {
32 self.generic_nodes
33 }
34 pub fn generic(&self) -> &str {
35 &self.generic
36 }
37 pub fn qualifier_nodes(&self) -> &'a [RdNode] {
38 self.qualifier_nodes
39 }
40 pub fn qualifier(&self) -> &str {
42 &self.qualifier
43 }
44}
45
46fn kind(tag: &RdTag) -> Option<RdMethodKind> {
47 match tag {
48 RdTag::Method => Some(RdMethodKind::Method),
49 RdTag::S3Method => Some(RdMethodKind::S3Method),
50 RdTag::S4Method => Some(RdMethodKind::S4Method),
51 _ => None,
52 }
53}
54
55impl RdNode {
56 pub fn method(&self, base_path: &RdPath) -> Option<RdMethod<'_>> {
57 self.inspect_method(base_path).ok().flatten()
58 }
59
60 pub fn inspect_method(&self, base_path: &RdPath) -> Result<Option<RdMethod<'_>>, RdShapeError> {
61 let tagged = match self {
62 RdNode::Tagged(tagged) => tagged,
63 RdNode::Raw(raw) => {
64 let Some(tag) = raw.tag().map(RdTag::from_rd_tag) else {
65 return Ok(None);
66 };
67 if kind(&tag).is_some() {
68 return Err(shape(
69 base_path.clone(),
70 Some(tag),
71 RdShapeErrorKind::UnexpectedNode {
72 expected: RdExpectedNode::Tagged,
73 actual: RdNodeKind::Raw,
74 },
75 ));
76 }
77 return Ok(None);
78 }
79 _ => return Ok(None),
80 };
81 let Some(kind) = kind(tagged.tag()) else {
82 return Ok(None);
83 };
84 if tagged.option().is_some() {
85 return Err(shape(
86 base_path.clone(),
87 Some(tagged.tag().clone()),
88 RdShapeErrorKind::UnexpectedOption,
89 ));
90 }
91 let children = tagged.children();
92 if children.len() != 2 {
93 return Err(shape(
94 base_path.clone(),
95 Some(tagged.tag().clone()),
96 RdShapeErrorKind::WrongArity {
97 expected: RdArity::Exactly(2),
98 actual: children.len(),
99 },
100 ));
101 }
102 for (index, child) in children.iter().enumerate() {
103 if child.as_group().is_none() {
104 return Err(shape(
105 base_path.with_child(index),
106 Some(tagged.tag().clone()),
107 RdShapeErrorKind::UnexpectedNode {
108 expected: RdExpectedNode::Group,
109 actual: RdNodeKind::of(child),
110 },
111 ));
112 }
113 }
114 let generic_nodes = children[0].as_group().unwrap().children();
115 let qualifier_nodes = children[1].as_group().unwrap().children();
116 let generic = concat_exact(
117 generic_nodes,
118 RdNodeKind::Text,
119 &base_path.with_child(0),
120 tagged.tag(),
121 )?;
122 let qualifier = concat_exact(
123 qualifier_nodes,
124 RdNodeKind::Text,
125 &base_path.with_child(1),
126 tagged.tag(),
127 )?;
128 Ok(Some(RdMethod {
129 path: base_path.clone(),
130 kind,
131 generic_nodes,
132 generic,
133 qualifier_nodes,
134 qualifier,
135 }))
136 }
137}