verilization_bindings_c_api_core/
lib.rs1use verilization_compiler::{lang, model, parser, load_all_models, VError, MemoryOutputHandler};
5use lang::{GeneratorError, Language, LanguageRegistry, LanguageHandler};
6
7use std::ffi::{c_void, OsString};
8use std::collections::HashMap;
9
10
11
12#[repr(C)]
14pub struct APIString {
15 length: usize,
16 data: [u8; 0],
17}
18
19impl APIString {
20 unsafe fn allocate(s: &str) -> *mut APIString {
21 let ptr = verilization_mem_alloc(std::mem::size_of::<APIString>() + s.len());
22 let api_str = ptr as *mut APIString;
23 (*api_str).length = s.len();
24 std::ptr::copy_nonoverlapping(s.as_ptr(), (*api_str).data.as_mut_ptr(), s.len());
25 api_str
26 }
27
28 fn to_str<'a>(&'a self) -> Option<&'a str> {
29 let data = &self.data as *const u8;
30 unsafe { std::str::from_utf8(std::slice::from_raw_parts(data, self.length)).ok() }
31 }
32}
33
34#[repr(C)]
38pub struct APIResult<T> {
39 is_error: usize,
40 data: APIResultPtr<T>,
41}
42
43#[repr(C)]
45pub union APIResultPtr<T> {
46 error: *mut APIString,
47 value: *mut T,
48}
49
50#[repr(C)]
52pub struct LanguageOption {
53 name: *mut APIString,
54 value: *mut APIString,
55}
56
57#[repr(C)]
59pub struct OutputFileEntry {
60 name: *mut APIString,
61 length: usize,
62 content: *mut u8,
63}
64
65#[repr(C)]
67pub struct OutputFileMap {
68 length: usize,
69 entries: [OutputFileEntry; 0],
70}
71
72impl OutputFileMap {
73 unsafe fn allocate(map: &HashMap<String, Vec<u8>>) -> *mut OutputFileMap {
74 let ptr = verilization_mem_alloc(std::mem::size_of::<OutputFileMap>() + map.len() * std::mem::size_of::<OutputFileEntry>()) as *mut OutputFileMap;
75 (*ptr).length = map.len();
76
77 let entries = std::slice::from_raw_parts_mut((*ptr).entries.as_mut_ptr(), map.len());
78 for (index, (name, data)) in map.iter().enumerate() {
79 let entry: &mut OutputFileEntry = &mut entries[index];
80 entry.name = APIString::allocate(name);
81 entry.length = data.len();
82
83 let buffer = verilization_mem_alloc(data.len());
84 entry.content = buffer;
85 std::ptr::copy_nonoverlapping(data.as_ptr(), buffer, data.len());
86 }
87
88 ptr
89 }
90}
91
92
93#[no_mangle]
98pub unsafe extern "C" fn verilization_mem_alloc(size: usize) -> *mut u8 {
99 std::alloc::alloc(std::alloc::Layout::from_size_align(size, std::mem::size_of::<*mut c_void>()).unwrap())
100}
101
102#[no_mangle]
108pub unsafe extern "C" fn verilization_mem_free(size: usize, ptr: *mut u8) {
109 std::alloc::dealloc(ptr, std::alloc::Layout::from_size_align(size, std::mem::size_of::<*mut c_void>()).unwrap())
110}
111
112#[no_mangle]
118pub unsafe extern "C" fn verilization_parse(nfiles: usize, files: *const *const APIString, result: *mut APIResult<model::Verilization>) {
119 let files = std::slice::from_raw_parts(files, nfiles);
120
121 *result = match verilization_parse_impl(files) {
122 Ok(model) => APIResult {
123 is_error: 0,
124 data: APIResultPtr {
125 value: Box::into_raw(Box::new(model)),
126 },
127 },
128 Err(err) => APIResult {
129 is_error: 1,
130 data: APIResultPtr {
131 error: APIString::allocate(&format!("{:?}", err)),
132 },
133 },
134 }
135}
136
137unsafe fn verilization_parse_impl(files: &[*const APIString]) -> Result<model::Verilization, VError> {
138 let models = files.iter().map(|content| {
139 let content = content.as_ref().expect("Pointer was null").to_str().expect("Invalid String");
140 let (_, model) = parser::parse_model(content)?;
141 let model = model()?;
142 Ok(model)
143 });
144
145 load_all_models(models)
146}
147
148#[no_mangle]
150pub unsafe extern "C" fn verilization_destroy(verilization: *mut model::Verilization) {
151 Box::from_raw(verilization);
152}
153
154pub unsafe fn verilization_generate_impl<Registry: LanguageRegistry>(verilization: *const model::Verilization, language: *const APIString, noptions: usize, options: *const LanguageOption, result: *mut APIResult<OutputFileMap>, registry: &Registry) {
162 *result = match verilization_generate_impl_result(verilization, language, noptions, options, registry) {
163 Ok(map) => APIResult {
164 is_error: 0,
165 data: APIResultPtr {
166 value: map,
167 },
168 },
169 Err(err) => APIResult {
170 is_error: 1,
171 data: APIResultPtr {
172 error: APIString::allocate(&format!("{:?}", err)),
173 },
174 },
175 }
176}
177
178
179unsafe fn verilization_generate_impl_result<Registry: LanguageRegistry>(verilization: *const model::Verilization, language: *const APIString, noptions: usize, options: *const LanguageOption, registry: &Registry) -> Result<*mut OutputFileMap, GeneratorError> {
180 let verilization = verilization.as_ref().expect("Verilization pointer is null");
181 let language = language.as_ref().expect("Language string is null").to_str().expect("Language is invalid text");
182 let options = std::slice::from_raw_parts(options, noptions)
183 .iter()
184 .map(|option| {
185 let name = option.name.as_ref().expect("Option name is null").to_str().expect("Invalid option name text");
186 let value = option.value.as_ref().expect("Option value is null").to_str().expect("Invalid option value text");
187 (name, value)
188 })
189 .collect::<Vec<_>>();
190
191 let mut output = MemoryOutputHandler {
192 files: HashMap::new(),
193 };
194
195 match registry.handle_language(language, &mut VerilizationGenerateLang { verilization: verilization, options: options, output: &mut output, }) {
196 Some(result) => result?,
197 None =>Err(GeneratorError::UnknownLanguage(String::from(language)))?,
198 }
199
200 Ok(OutputFileMap::allocate(&output.files))
201}
202
203struct VerilizationGenerateLang<'a, Output> {
204 verilization: &'a model::Verilization,
205 options: Vec<(&'a str, &'a str)>,
206 output: &'a mut Output,
207}
208
209impl <'a, Output: for<'output> lang::OutputHandler<'output>> LanguageHandler for VerilizationGenerateLang<'a, Output> {
210 type Result = Result<(), GeneratorError>;
211
212 fn run<Lang: Language>(&mut self) -> Self::Result {
213 let mut lang_options = Lang::empty_options();
214 for (name, value) in &self.options {
215 Lang::add_option(&mut lang_options, name, OsString::from(value))?;
216 }
217 let lang_options = Lang::finalize_options(lang_options)?;
218
219 Lang::generate(self.verilization, lang_options, self.output)
220 }
221}
222
223