1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
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()); } }