flatbuffers_tools/
lib.rs

1//! Flatbuffers related tools
2
3#![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)]
11///Possible parser errors
12pub enum ParseError {
13    ///Service definition is encountered, but there is no opening bracket
14    NoStartingBracket,
15    ///Cannot determine return type
16    NoReturnType(String),
17    ///Method definition has invalid arguments
18    InvalidMethodArgs(String),
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22///rpc method
23pub struct RpcMethod {
24    ///Method's name
25    pub name: String,
26    ///List of arguments
27    pub arguments: Vec<String>,
28    ///Return type
29    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)]
62///rpc_service definition
63pub struct RpcService {
64    ///Service name
65    pub name: String,
66    ///List of service methods
67    pub methods: Vec<RpcMethod>
68}
69
70impl RpcService {
71    ///Gets formatter to generate RPC method defines which are upper case constants corresponding
72    ///to RPC method name.
73    pub fn as_rpc_method_defines(&self) -> RpcMethodDefines<'_> {
74        RpcMethodDefines {
75            service: self
76        }
77    }
78}
79
80///rpc_service parser
81pub struct ParserIter<T> {
82    lines: T,
83}
84
85impl<I: AsRef<str>, T: Iterator<Item=I>> ParserIter<T> {
86    ///Creates new parser from iterator over lines.
87    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}