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