1use crate::bls::{BLSEntry, KeyValue};
21use crate::cmdline::{CmdlineHandler, CmdlineParam};
22use std::ffi::{CStr, CString};
23use std::os::raw::{c_char};
24
25#[repr(C)]
26pub struct CTraitReference {
27 data: *mut std::os::raw::c_void,
28 vtable: *mut std::os::raw::c_void
29}
30
31fn c_array_to_vector(c_array: *const *const c_char) -> Result<Vec<String>, &'static str> {
32 let start: *mut usize = c_array as *mut usize;
34 let mut end: isize = 0;
35 let mut boxed_address = unsafe { std::ptr::read (start.offset(end))};
36 while boxed_address != 0 {
37 boxed_address = unsafe { std::ptr::read (start.offset(end))};
38 end += 1;
39 }
40 end -= 1;
41
42 let ptr_slice = unsafe { std::slice::from_raw_parts(c_array, end as usize) };
43 let vector: Vec<_> = ptr_slice.iter()
44 .map(|cstr| { unsafe { CStr::from_ptr(*cstr) }})
45 .map(|cstr| { cstr.to_str() })
46 .filter_map(|cstr| { match cstr {
47 Err(_) => None,
48 Ok(elements) => Some(elements)
49 }})
50 .map(|element| { String::from(element) })
51 .collect();
52
53 if vector.len() != end as usize {
54 return Err("could not convert pointer to vector");
55 }
56
57 Ok(vector)
58}
59
60fn generic_cmdline_handler(env: &mut dyn CmdlineHandler, params: *const *const c_char, op: &dyn Fn(&mut dyn CmdlineHandler, &[String]) -> std::io::Result<()>) -> c_char {
61 let params = match c_array_to_vector(params) {
62 Ok(params) => params,
63 Err(_) => { return 0; }
64 };
65
66 match op(env, ¶ms[..]) {
67 Ok(_) => 1,
68 Err(_) => 0
69 }
70}
71
72fn generic_cmdline_get (env: &mut dyn CmdlineHandler, param: *const c_char) -> *mut CmdlineParam {
73 let param = match unsafe { CStr::from_ptr(param) }.to_str() {
74 Ok(param) => param,
75 Err(_) => { return std::ptr::null_mut(); }
76 };
77
78 let cmdline = env.cmdline_get(&String::from(param));
79
80 match cmdline {
81 Ok(cmdline) => {
82 let cmdline = Box::new(cmdline);
83 Box::into_raw(cmdline)
84 }
85 Err(_) => std::ptr::null_mut()
86 }
87}
88
89#[allow(dead_code)]
90#[no_mangle]
91pub extern "C" fn bls_cmdline_param_foreach (cmdline: *mut CmdlineParam, lambda: extern "C" fn (val: *const c_char, user_data: *mut std::ffi::c_void), user_data: *mut std::ffi::c_void) {
92 let cmdline = unsafe{ Box::from_raw(cmdline) };
93 for param_value in cmdline.iter() {
94 match param_value {
95 Some(param_value) => {
96 let c_param_value = CString::new(param_value.as_str()).unwrap();
97
98 lambda (c_param_value.as_ptr(), user_data);
99 }
100 None => {
101 lambda (std::ptr::null(), user_data);
102 }
103 }
104 };
105 Box::into_raw(cmdline);
106}
107
108
109#[allow(dead_code)]
110#[no_mangle]
111pub extern "C" fn bls_cmdline_param_get_size (cmdline: *mut CmdlineParam) -> usize {
112 let cmdline = unsafe{ Box::from_raw(cmdline) };
113 let size = cmdline.len();
114 Box::into_raw(cmdline);
115 size
116}
117
118#[allow(dead_code)]
119#[no_mangle]
120pub extern "C" fn bls_cmdline_param_destroy(cmdline: *mut CmdlineParam) {
121 unsafe{ Box::from_raw(cmdline) };
122}
123
124#[allow(dead_code)]
127#[no_mangle]
128pub extern "C" fn bls_entry_new(entry: *const c_char) -> *mut BLSEntry {
129 let entry = match unsafe { CStr::from_ptr(entry) }.to_str() {
130 Ok(entry_name) => String::from(entry_name),
131 Err(_) => { return std::ptr::null_mut(); }
132 };
133
134 if let Ok(entry) = BLSEntry::new(&entry) {
135 Box::into_raw(Box::new(entry))
136 } else {
137 std::ptr::null_mut()
138 }
139}
140
141#[allow(dead_code)]
142#[no_mangle]
143pub extern "C" fn bls_entry_destroy(entry: *mut BLSEntry) {
144 unsafe { Box::from_raw(entry) };
145}
146
147#[allow(dead_code)]
148#[no_mangle]
149pub extern "C" fn bls_entry_get (entry: *mut BLSEntry, key: *const c_char) -> *mut KeyValue {
150 let entry = unsafe { Box::from_raw(entry) };
151 let key = match unsafe { CStr::from_ptr(key) }.to_str() {
152 Ok(key) => key,
153 _ => { return std::ptr::null_mut(); }
154 };
155
156 match entry.get(key) {
157 Ok(keyvalue) => {
158 let keyvalue = Box::new(keyvalue);
159 Box::into_raw(keyvalue)
160 },
161 Err(_) => std::ptr::null_mut()
162 }
163}
164
165#[allow(dead_code)]
166#[no_mangle]
167pub extern "C" fn bls_entry_set (entry: *mut BLSEntry, key: *const c_char,
168 value: *const *const c_char) -> c_char {
169 let entry = unsafe { Box::from_raw(entry) };
170 let key = match unsafe { CStr::from_ptr(key) }.to_str() {
171 Ok(key) => key,
172 _ => { return 0; }
173 };
174
175 let value = match c_array_to_vector(value) {
176 Ok(value) => value,
177 Err(_) => { return 0; }
178 };
179
180 let ret = match entry.set(key, &value) {
181 Ok(_) => 1,
182 _ => 0
183 };
184 Box::into_raw(entry);
185 ret
186}
187
188#[allow(dead_code)]
189#[no_mangle]
190pub extern "C" fn bls_entry_remove (entry: *mut BLSEntry, key: *const c_char) -> c_char {
191 let entry = unsafe { Box::from_raw(entry) };
192 let key = match unsafe { CStr::from_ptr(key) }.to_str() {
193 Ok(key) => key,
194 _ => { return 0; }
195 };
196
197 let ret = match entry.remove(key) {
198 Ok(_) => 1,
199 _ => 0
200 };
201 Box::into_raw(entry);
202 ret
203}
204
205#[allow(dead_code)]
208#[no_mangle]
209pub extern "C" fn bls_entry_list () -> *mut Vec<String> {
210 match BLSEntry::get_bls_entries() {
211 Ok(entries) => {
212 Box::into_raw(Box::new(entries))
213 },
214 Err(_) => std::ptr::null_mut()
215 }
216}
217
218#[allow(dead_code)]
219#[no_mangle]
220pub extern "C" fn bls_entry_list_destroy(list: *mut Vec<String>) {
221 let _ = unsafe { Box::from_raw(list) };
222}
223
224#[allow(dead_code)]
227#[no_mangle]
228pub extern "C" fn bls_entry_to_cmdline (entry: *mut BLSEntry) -> CTraitReference {
229 let mut entry = unsafe { Box::from_raw(entry) };
230 let ret: CTraitReference = {
231 let handler: &mut dyn CmdlineHandler = &mut *entry;
232 unsafe { std::mem::transmute::<&mut dyn CmdlineHandler,CTraitReference> (handler) }
233 };
234 Box::into_raw(entry);
235 ret
236}
237
238#[allow(dead_code)]
239#[no_mangle]
240pub extern "C" fn bls_entry_list_to_cmdline (list: *mut Vec<String>) -> CTraitReference {
241 let mut list = unsafe { Box::from_raw(list) };
242 let ret: CTraitReference = {
243 let handler: &mut dyn CmdlineHandler = &mut *list;
244 unsafe { std::mem::transmute::<&mut dyn CmdlineHandler,CTraitReference> (handler) }
245 };
246 Box::into_raw(list);
247 ret
248}
249
250#[allow(dead_code)]
251#[no_mangle]
252pub extern "C" fn bls_cmdline_get (handler: CTraitReference, param: *mut c_char) -> *mut CmdlineParam {
253 let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
254 generic_cmdline_get (handler, param)
255}
256
257#[allow(dead_code)]
258#[no_mangle]
259pub extern "C" fn bls_cmdline_set (handler: CTraitReference, params: *const *const c_char) -> c_char {
260 let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
261 generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_set(p) })
262
263}
264
265#[allow(dead_code)]
266#[no_mangle]
267pub extern "C" fn bls_cmdline_add (handler: CTraitReference, params: *const *const c_char) -> c_char {
268 let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
269 generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_add(p) })
270}
271
272#[allow(dead_code)]
273#[no_mangle]
274pub extern "C" fn bls_cmdline_remove (handler: CTraitReference, params: *const *const c_char) -> c_char {
275 let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
276 generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_remove(p) })
277}
278
279#[allow(dead_code)]
280#[no_mangle]
281pub extern "C" fn bls_cmdline_clear (handler: CTraitReference, params: *const *const c_char) -> c_char {
282 let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
283 generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_clear(p) })
284}