1use super::AsAlfa;
5use super::PrettyPrint;
6use super::QualifiedName;
7use std::fmt;
8
9#[derive(Debug, PartialEq, Clone)]
10pub enum FunctionInputArg {
11 Atomic(String),
13 AtomicBag(String),
15 AnyAtomicBag,
17 AnyAtomic,
19 AnyAtomicOrBag,
21 Function,
23}
24
25#[derive(Debug, PartialEq, Clone)]
30pub enum FunctionOutputArg {
31 Atomic(String),
33 AtomicBag(String),
35 AnyAtomicBag,
37 AnyAtomic,
39}
40
41#[derive(Debug, PartialEq, Clone)]
43pub struct FunctionInputs {
44 pub args: Vec<FunctionInputArg>,
46 pub wildcard: bool,
48}
49
50#[derive(Debug, Clone)]
52pub struct Function {
53 pub id: String,
54 pub ns: Vec<String>,
56 pub function_uri: String,
58 pub input_args: FunctionInputs,
60 pub output_arg: FunctionOutputArg,
62}
63
64impl AsAlfa for Function {
65 fn to_alfa(&self, indent_level: usize) -> String {
66 let indent = " ".repeat(indent_level);
67 let mut output = format!(
70 "{}function {} = \"{}\" : ",
71 indent, self.id, self.function_uri
72 );
73 for a in &self.input_args.args {
74 output.push_str(&a.to_string());
75 output.push(' ');
76 }
77 if self.input_args.wildcard {
78 output.push_str("* ");
79 }
80 output.push_str("-> ");
82 output.push_str(&self.output_arg.to_string());
83 output.push('\n');
84 output
85 }
86}
87
88impl PartialEq for Function {
90 fn eq(&self, other: &Self) -> bool {
91 self.id == other.id
92 && self.ns == other.ns
93 && self.function_uri == other.function_uri
94 && self.input_args == other.input_args
95 && self.output_arg == other.output_arg
96 }
97}
98
99impl QualifiedName for Function {
101 fn fully_qualified_name(&self) -> Option<String> {
102 let mut qn = self.ns.join(".");
103 if !self.ns.is_empty() {
104 qn.push('.');
105 }
106 qn.push_str(&self.id);
107 Some(qn.to_string())
108 }
109}
110
111impl PrettyPrint for Function {
113 fn pretty_print(&self, indent_level: usize) {
114 let indent = " ".repeat(indent_level);
115 print!("{indent}{self}");
116 println!();
117 }
118}
119
120impl fmt::Display for Function {
122 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
123 let mut s: String = String::default();
124 s.push_str(&format!("fn {} <{}> ", self.id, self.function_uri));
125 let args: Vec<String> = self
127 .input_args
128 .args
129 .iter()
130 .map(std::string::ToString::to_string)
131 .collect();
132 s.push('(');
133 s.push_str(&args.join(", "));
134 if self.input_args.wildcard {
135 s.push('*');
136 }
137 s.push(')');
138 s.push_str(&format!(" ==> {}", self.output_arg));
140 write!(f, "{s}")
141 }
142}
143
144impl fmt::Display for FunctionInputArg {
145 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146 match self {
147 FunctionInputArg::AnyAtomic => write!(f, "anyAtomic"),
148 FunctionInputArg::AnyAtomicBag => write!(f, "bag[anyAtomic]"),
149 FunctionInputArg::AnyAtomicOrBag => write!(f, "anyAtomicOrBag"),
150 FunctionInputArg::Atomic(s) => write!(f, "{s}"),
151 FunctionInputArg::AtomicBag(s) => write!(f, "bag[{s}]"),
152 FunctionInputArg::Function => write!(f, "function"),
153 }
154 }
155}
156
157impl fmt::Display for FunctionOutputArg {
158 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159 match self {
160 FunctionOutputArg::AnyAtomic => write!(f, "anyAtomic"),
161 FunctionOutputArg::AnyAtomicBag => write!(f, "bag[anyAtomic]"),
162 FunctionOutputArg::Atomic(s) => write!(f, "{s}"),
163 FunctionOutputArg::AtomicBag(s) => write!(f, "bag[{s}]"),
164 }
165 }
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171
172 #[test]
173 fn test_serialize() {
174 let args = vec![
177 FunctionInputArg::Atomic("string".to_owned()),
178 FunctionInputArg::AtomicBag("boolean".to_owned()),
179 FunctionInputArg::AnyAtomic,
180 FunctionInputArg::AnyAtomicBag,
181 FunctionInputArg::AnyAtomicOrBag,
182 FunctionInputArg::Function,
183 ];
184 let output_arg = FunctionOutputArg::AtomicBag("string".to_owned());
185 let f = Function {
186 id: "fn_name".to_owned(),
187 ns: vec!["main".to_owned()],
188 function_uri: "urn:oasis:sample".to_owned(),
189 input_args: FunctionInputs {
190 args,
191 wildcard: true,
192 },
193 output_arg,
194 };
195 let a = f.to_alfa(1);
196 assert_eq!(
197 a,
198 " function fn_name = \"urn:oasis:sample\" : string bag[boolean] anyAtomic bag[anyAtomic] anyAtomicOrBag function * -> bag[string]\n"
199 );
200 }
201}