cog_idl/
lib.rs

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}