mod parser;
pub use parser::ParseError;
use std::{
fs::{read_dir, read_to_string},
path::Path,
};
use parser::parse_module;
pub fn load_api_from_dir<P: AsRef<Path>>(path: P) -> Result<Api, ParseError> {
let mut api = Api {
modules: Vec::new(),
};
for path in read_dir(path).unwrap() {
let path = path.unwrap().path();
let module_name = path.file_stem().unwrap().to_str().unwrap();
let module_str = read_to_string(&path).unwrap();
let module = load_module_from_str(module_name, &module_str)?;
api.modules.push(module);
}
Ok(api)
}
pub fn load_module_from_str<S: ToString>(name: S, cog: &str) -> Result<Module, ParseError> {
parse_module(name.to_string(), cog)
}
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Api {
pub modules: Vec<Module>,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Module {
pub name: String,
pub documentation: Option<String>,
pub interfaces: Vec<Interface>,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Interface {
pub name: String,
pub documentation: Option<String>,
pub functions: Vec<Function>,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Function {
pub name: String,
pub documentation: Option<String>,
pub parameters: Vec<Parameter>,
pub return_type: Option<Type>,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Parameter {
pub name: String,
pub type_: Type,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Type {
pub modifier: TypeModifier,
pub type_name: TypeName,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum TypeModifier {
None,
Pointer,
Reference,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum TypeName {
CString,
Any,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn single_interface() {
let code = "interface foo { fn bar(); }";
let result = load_module_from_str("test", &code);
assert!(result.is_ok());
let module = result.unwrap();
assert_eq!(module.interfaces.len(), 1);
let interface = &module.interfaces[0];
assert_eq!(interface.name, "foo");
assert_eq!(interface.functions.len(), 1);
let function = &interface.functions[0];
assert_eq!(function.name, "bar");
}
#[test]
fn comment_at_end_of_file() {
let code = "// comment";
let result = load_module_from_str("test", &code);
assert!(result.is_ok());
}
}