1use crate::osrf::app;
2use crate::osrf::message;
3use crate::osrf::session;
4use crate::EgResult;
5use crate::EgValue;
6use json::JsonValue;
7use std::fmt;
8
9pub type MethodHandler = fn(
10 &mut Box<dyn app::ApplicationWorker>,
11 &mut session::ServerSession,
12 message::MethodCall,
13) -> EgResult<()>;
14
15#[derive(Debug, Copy, Clone, PartialEq)]
16pub enum ParamCount {
17 Any,
18 Zero,
19 Exactly(u8),
20 AtLeast(u8),
21 Range(u8, u8), }
23
24impl ParamCount {
25 pub fn matches(pc: &ParamCount, count: u8) -> bool {
37 match *pc {
38 ParamCount::Any => true,
39 ParamCount::Zero => count == 0,
40 ParamCount::Exactly(c) => count == c,
41 ParamCount::AtLeast(c) => count >= c,
42 ParamCount::Range(s, e) => s <= count && e >= count,
43 }
44 }
45
46 pub fn minimum(&self) -> u8 {
49 match *self {
50 ParamCount::Any => 0,
51 ParamCount::Zero => 0,
52 ParamCount::Exactly(c) => c,
53 ParamCount::AtLeast(c) => c,
54 ParamCount::Range(s, _) => s,
55 }
56 }
57}
58
59impl fmt::Display for ParamCount {
60 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61 match *self {
62 ParamCount::Any => write!(f, "Any"),
63 ParamCount::Zero => write!(f, "Zero"),
64 ParamCount::Exactly(c) => write!(f, "Exactly {}", c),
65 ParamCount::AtLeast(c) => write!(f, "AtLeast {}", c),
66 ParamCount::Range(s, e) => write!(f, "Range {}..{}", s, e),
67 }
68 }
69}
70
71#[derive(Clone, Copy, Debug)]
73pub enum ParamDataType {
74 String,
75 Number,
76 Array,
77 Object, Boolish,
79 Scalar, Any,
81}
82
83impl fmt::Display for ParamDataType {
84 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85 let s = match *self {
86 ParamDataType::String => "String",
87 ParamDataType::Number => "Number",
88 ParamDataType::Array => "Array",
89 ParamDataType::Object => "Object",
90 ParamDataType::Boolish => "Boolish",
91 ParamDataType::Scalar => "Scalar",
92 ParamDataType::Any => "Any",
93 };
94 write!(f, "{s}")
95 }
96}
97
98impl ParamDataType {
99 pub fn matches(&self, param: &EgValue) -> bool {
104 match *self {
105 ParamDataType::String => param.is_string(),
106 ParamDataType::Number => param.is_number(),
107 ParamDataType::Array => param.is_array(),
108 ParamDataType::Object => param.is_object(),
109 ParamDataType::Boolish => {
110 param.is_boolean() || param.is_number() || param.is_string() || param.is_null()
111 }
112 ParamDataType::Scalar => {
113 param.is_boolean() || param.is_number() || param.is_string() || param.is_null()
114 }
115 ParamDataType::Any => true,
116 }
117 }
118}
119
120#[derive(Clone, Debug)]
121pub struct StaticParam {
122 pub name: &'static str,
123 pub datatype: ParamDataType,
124 pub desc: &'static str,
125}
126
127#[derive(Clone, Debug)]
128pub struct Param {
129 pub name: String,
130 pub datatype: ParamDataType,
131 pub desc: Option<String>,
132}
133
134impl Param {
135 pub fn to_eg_value(&self) -> EgValue {
136 EgValue::from_json_value_plain(json::object! {
137 "name": self.name.as_str(),
138 "datatype": self.datatype.to_string(),
139 "desc": match self.desc.as_ref() {
140 Some(d) => d.as_str().into(),
141 _ => JsonValue::Null,
142 }
143 })
144 }
145}
146
147pub struct StaticMethodDef {
150 pub name: &'static str,
151 pub desc: &'static str,
152 pub param_count: ParamCount,
153 pub handler: MethodHandler,
154 pub params: &'static [StaticParam],
155}
156
157impl StaticMethodDef {
158 pub fn name(&self) -> &str {
159 self.name
160 }
161 pub fn param_count(&self) -> &ParamCount {
162 &self.param_count
163 }
164 pub fn handler(&self) -> &MethodHandler {
165 &self.handler
166 }
167
168 pub fn into_method(&self, api_prefix: &str) -> MethodDef {
170 let mut params: Vec<Param> = Vec::new();
171
172 for p in self.params {
173 let mut param = Param {
174 name: p.name.to_string(),
175 datatype: p.datatype,
176 desc: None,
177 };
178
179 if !p.desc.is_empty() {
180 param.desc = Some(p.desc.to_string());
181 }
182
183 params.push(param)
184 }
185
186 let mut m = MethodDef::new(
187 &format!("{}.{}", api_prefix, self.name()),
188 *self.param_count(),
189 self.handler,
190 );
191
192 if !params.is_empty() {
193 m.params = Some(params);
194 }
195
196 if !self.desc.is_empty() {
197 m.desc = Some(self.desc.to_string());
198 }
199
200 m
201 }
202}
203
204#[derive(Clone)]
205pub struct MethodDef {
206 pub name: String,
207 pub desc: Option<String>,
208 pub param_count: ParamCount,
209 pub handler: MethodHandler,
210 pub params: Option<Vec<Param>>,
211}
212
213impl MethodDef {
214 pub fn new(name: &str, param_count: ParamCount, handler: MethodHandler) -> MethodDef {
215 MethodDef {
216 handler,
217 param_count,
218 params: None,
219 desc: None,
220 name: name.to_string(),
221 }
222 }
223
224 pub fn param_count(&self) -> &ParamCount {
225 &self.param_count
226 }
227
228 pub fn handler(&self) -> MethodHandler {
229 self.handler
230 }
231
232 pub fn name(&self) -> &str {
233 &self.name
234 }
235
236 pub fn set_name(&mut self, name: &str) {
237 self.name = name.to_string();
238 }
239
240 pub fn params(&self) -> Option<&Vec<Param>> {
241 self.params.as_ref()
242 }
243
244 pub fn desc(&self) -> Option<&str> {
245 self.desc.as_deref()
246 }
247 pub fn set_desc(&mut self, desc: &str) {
248 self.desc = Some(desc.to_string());
249 }
250 pub fn add_param(&mut self, param: Param) {
251 let params = match self.params.as_mut() {
252 Some(p) => p,
253 None => {
254 self.params = Some(Vec::new());
255 self.params.as_mut().unwrap()
256 }
257 };
258
259 params.push(param);
260 }
261
262 pub fn to_eg_value(&self) -> EgValue {
263 let mut pa = EgValue::new_array();
264 if let Some(params) = self.params() {
265 for param in params {
266 pa.push(param.to_eg_value()).expect("Is Array");
267 }
268 }
269
270 EgValue::from_json_value_plain(json::object! {
271 "api_name": self.name(),
272 "argc": self.param_count().to_string(),
273 "params": pa.into_json_value(),
274 "stream": JsonValue::Boolean(true),
276 "desc": match self.desc() {
277 Some(d) => d.into(),
278 _ => JsonValue::Null,
279 }
280 })
281 }
282
283 pub fn to_summary_string(&self) -> String {
285 let mut s = self.name().to_string();
286
287 match self.param_count {
288 ParamCount::Zero => {}
289 _ => s += " (",
290 }
291
292 if let Some(params) = self.params() {
293 let minimum = self.param_count.minimum();
294 for (idx, param) in params.iter().enumerate() {
295 let required = if idx <= minimum as usize {
296 "*" } else {
298 ""
299 };
300
301 s += &format!("{required}'{}',", param.name);
302 }
303 s.pop(); } else if self.param_count == ParamCount::Any {
305 s += "..";
306 }
307
308 if let ParamCount::AtLeast(_) = self.param_count {
309 s += ",..";
310 }
311
312 match self.param_count {
313 ParamCount::Zero => {}
314 _ => s += ")",
315 }
316
317 s
318 }
319}