1mod parser;
2
3pub use parser::ParseError;
4
5use std::{
6 fs::{read_dir, read_to_string},
7 path::Path,
8};
9
10use parser::parse_module;
11
12pub fn load_api_from_dir<P: AsRef<Path>>(path: P) -> Result<Api, ParseError> {
13 let mut api = Api {
14 modules: Vec::new(),
15 };
16
17 for path in read_dir(path).unwrap() {
18 let path = path.unwrap().path();
19
20 let module_name = path.file_stem().unwrap().to_str().unwrap();
21
22 let module_str = read_to_string(&path).unwrap();
23 let module = load_module_from_str(module_name, &module_str)?;
24
25 api.modules.push(module);
26 }
27
28 Ok(api)
29}
30
31pub fn load_module_from_str<S: ToString>(name: S, cog: &str) -> Result<Module, ParseError> {
32 parse_module(name.to_string(), cog)
33}
34
35#[cfg(feature = "serde")]
36use serde::{Serialize, Deserialize};
37
38#[derive(Debug)]
39#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
40pub struct Api {
41 pub modules: Vec<Module>,
42}
43
44#[derive(Debug)]
45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
46pub struct Module {
47 pub name: String,
48 pub documentation: Option<String>,
49 pub interfaces: Vec<Interface>,
50}
51
52#[derive(Debug)]
53#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
54pub struct Interface {
55 pub name: String,
56 pub documentation: Option<String>,
57 pub functions: Vec<Function>,
58}
59
60#[derive(Debug)]
61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
62pub struct Function {
63 pub name: String,
64 pub documentation: Option<String>,
65 pub parameters: Vec<Parameter>,
66 pub return_type: Option<Type>,
67}
68
69#[derive(Debug)]
70#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
71pub struct Parameter {
72 pub name: String,
73 pub type_: Type,
74}
75
76#[derive(Debug)]
77#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
78pub struct Type {
79 pub modifier: TypeModifier,
80 pub type_name: TypeName,
81}
82
83#[derive(Debug, PartialEq)]
84#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
85pub enum TypeModifier {
86 None,
87 Pointer,
88 Reference,
89}
90
91#[derive(Debug, PartialEq)]
92#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
93pub enum TypeName {
94 CString,
95 Any,
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn single_interface() {
104 let code = "interface foo { fn bar(); }";
105 let result = load_module_from_str("test", &code);
106
107 assert!(result.is_ok());
108
109 let module = result.unwrap();
110
111 assert_eq!(module.interfaces.len(), 1);
112
113 let interface = &module.interfaces[0];
114 assert_eq!(interface.name, "foo");
115 assert_eq!(interface.functions.len(), 1);
116
117 let function = &interface.functions[0];
118 assert_eq!(function.name, "bar");
119 }
120
121 #[test]
122 fn comment_at_end_of_file() {
123 let code = "// comment";
124 let result = load_module_from_str("test", &code);
125
126 assert!(result.is_ok());
127 }
128}