1#![warn(missing_docs)]
4#![cfg_attr(feature = "cargo-clippy", allow(clippy::style))]
5#![cfg_attr(rustfmt, rustfmt_skip)]
6
7mod gen;
8pub use gen::{RpcMethodDefines, RpcServiceImplDefines};
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum ParseError {
13 NoStartingBracket,
15 NoReturnType(String),
17 InvalidMethodArgs(String),
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct RpcMethod {
24 pub name: String,
26 pub arguments: Vec<String>,
28 pub return_type: String,
30}
31
32impl RpcMethod {
33 fn parse(line: &str) -> Result<Self, ParseError> {
34 let mut parts = line.split(':');
35 let method_args = parts.next().unwrap();
36 let return_type = match parts.next() {
37 Some(return_type) => return_type.trim().trim_end_matches(';'),
38 None => return Err(ParseError::NoReturnType(line.to_owned())),
39 };
40 let mut parts = method_args.split('(');
41 let name = parts.next().unwrap().trim();
42 let mut args = match parts.next() {
43 Some(args) => args.trim(),
44 None => return Err(ParseError::InvalidMethodArgs(method_args.to_owned())),
45 };
46 args = if let Some(args) = args.strip_suffix(')') {
47 args
48 } else {
49 return Err(ParseError::InvalidMethodArgs(method_args.to_owned()))
50 };
51 let arguments = args.split(',').map(str::to_owned).collect();
52
53 Ok(Self {
54 name: name.to_owned(),
55 arguments,
56 return_type: return_type.to_owned()
57 })
58 }
59}
60
61#[derive(Debug, Clone, PartialEq, Eq)]
62pub struct RpcService {
64 pub name: String,
66 pub methods: Vec<RpcMethod>
68}
69
70impl RpcService {
71 pub fn as_rpc_method_defines(&self) -> RpcMethodDefines<'_> {
74 RpcMethodDefines {
75 service: self
76 }
77 }
78}
79
80pub struct ParserIter<T> {
82 lines: T,
83}
84
85impl<I: AsRef<str>, T: Iterator<Item=I>> ParserIter<T> {
86 pub fn new(lines: T) -> Self {
88 Self {
89 lines
90 }
91 }
92}
93
94impl<I: AsRef<str>, T: Iterator<Item=I>> Iterator for ParserIter<T> {
95 type Item = Result<RpcService, ParseError>;
96
97 fn next(&mut self) -> Option<Self::Item> {
98 while let Some(line) = self.lines.next() {
99 let line = line.as_ref().trim();
100 if let Some(name) = line.strip_prefix("rpc_service") {
101 if let Some(name_end_idx) = name.find('{') {
102 let name = name[..name_end_idx].trim();
103 let mut methods = Vec::new();
104
105 while let Some(method) = self.lines.next() {
106 let method = method.as_ref().trim();
107 if method == "}" {
108 break;
109 }
110
111 match RpcMethod::parse(method) {
112 Ok(method) => methods.push(method),
113 Err(error) => return Some(Err(error)),
114 }
115 }
116
117 return Some(Ok(RpcService {
118 name: name.to_owned(),
119 methods,
120 }));
121 } else {
122 return Some(Err(ParseError::NoStartingBracket));
123 }
124 } else {
125 continue
126 }
127 }
128
129 None
130 }
131}