sails_idl_parser/ffi/ast/
mod.rs1use crate::ast;
2use std::{
3 ffi::{CString, c_char},
4 slice, str,
5};
6
7pub mod visitor;
8
9#[repr(C)]
10pub struct ParseResult {
11 program: *mut Program,
12 error: Error,
13}
14
15#[repr(C)]
16pub struct Error {
17 code: ErrorCode,
18 details: *const c_char,
19}
20
21#[repr(C)]
22#[derive(Debug, Clone, Copy, PartialEq)]
23pub enum ErrorCode {
24 Ok,
25 InvalidIDL,
26 ParseError,
27 NullPtr,
28}
29
30#[unsafe(no_mangle)]
34pub unsafe extern "C" fn parse_idl(idl_ptr: *const u8, idl_len: u32) -> *mut ParseResult {
35 let idl_slice = unsafe { slice::from_raw_parts(idl_ptr, idl_len as usize) };
36 let idl_str = match str::from_utf8(idl_slice) {
37 Ok(s) => s,
38 Err(e) => return create_parse_error(ErrorCode::ParseError, e, "validate IDL string"),
39 };
40
41 let program = match ast::parse_idl(idl_str) {
42 Ok(p) => p,
43 Err(e) => return create_parse_error(ErrorCode::ParseError, e, "parse IDL"),
44 };
45
46 let result = ParseResult {
47 error: Error {
48 code: ErrorCode::Ok,
49 details: std::ptr::null(),
50 },
51 program: Box::into_raw(Box::new(program)),
52 };
53
54 Box::into_raw(Box::new(result))
55}
56
57fn create_parse_error(
58 code: ErrorCode,
59 e: impl std::error::Error,
60 context: &'static str,
61) -> *mut ParseResult {
62 let details = CString::new(format!("{context}: {e}")).unwrap();
63 let result = ParseResult {
64 error: Error {
65 code,
66 details: details.into_raw(),
67 },
68 program: std::ptr::null_mut(),
69 };
70 Box::into_raw(Box::new(result))
71}
72
73#[unsafe(no_mangle)]
77pub unsafe extern "C" fn free_parse_result(result: *mut ParseResult) {
78 if result.is_null() {
79 return;
80 }
81 unsafe {
82 let result = Box::from_raw(result);
83 if result.error.code != ErrorCode::Ok {
84 let details = CString::from_raw(result.error.details as _);
85 drop(details);
86 }
87 }
88}
89
90pub type Program = ast::Program;
91
92#[repr(C)]
93pub struct Ctor {
94 raw_ptr: Ptr,
95}
96
97#[repr(C)]
98pub struct CtorFunc {
99 raw_ptr: Ptr,
100 name_ptr: *const u8,
101 name_len: u32,
102 docs_ptr: *const u8,
103 docs_len: u32,
104}
105
106#[repr(C)]
107pub struct Service {
108 raw_ptr: Ptr,
109 name_ptr: *const u8,
110 name_len: u32,
111}
112
113#[repr(C)]
114pub struct ServiceFunc {
115 raw_ptr: Ptr,
116 name_ptr: *const u8,
117 name_len: u32,
118 is_query: bool,
119 docs_ptr: *const u8,
120 docs_len: u32,
121}
122
123pub type ServiceEvent = EnumVariant;
124
125#[repr(C)]
126pub struct FuncParam {
127 raw_ptr: Ptr,
128 name_ptr: *const u8,
129 name_len: u32,
130}
131
132#[repr(C)]
133pub struct Type {
134 raw_ptr: Ptr,
135 name_ptr: *const u8,
136 name_len: u32,
137 docs_ptr: *const u8,
138 docs_len: u32,
139}
140
141#[repr(C)]
142pub struct TypeDecl {
143 raw_ptr: Ptr,
144}
145
146pub type PrimitiveType = ast::PrimitiveType;
147
148#[repr(C)]
149pub struct StructDef {
150 raw_ptr: Ptr,
151}
152
153#[repr(C)]
154pub struct StructField {
155 raw_ptr: Ptr,
156 name_ptr: *const u8,
157 name_len: u32,
158 docs_ptr: *const u8,
159 docs_len: u32,
160}
161
162#[repr(C)]
163pub struct EnumDef {
164 raw_ptr: Ptr,
165}
166
167#[repr(C)]
168pub struct EnumVariant {
169 raw_ptr: Ptr,
170 name_ptr: *const u8,
171 name_len: u32,
172 docs_ptr: *const u8,
173 docs_len: u32,
174}
175
176#[repr(transparent)]
177pub struct Ptr(*const ());
178
179impl<T> From<&T> for Ptr {
180 fn from(t: &T) -> Self {
181 Self(t as *const T as *const ())
182 }
183}
184
185impl<T> AsRef<T> for Ptr {
186 fn as_ref(&self) -> &T {
187 unsafe { (self.0 as *const T).as_ref() }.unwrap()
188 }
189}