rustfst_ffi/
symbol_table.rs

1use crate::{get, get_mut, wrap, CStateId, RUSTFST_FFI_RESULT};
2use ffi_convert::*;
3use std::ffi::{CStr, CString};
4use std::sync::Arc;
5
6use anyhow::{anyhow, format_err};
7use rustfst::SymbolTable;
8
9#[derive(RawPointerConverter)]
10pub struct CSymbolTable(pub(crate) Arc<SymbolTable>);
11
12/// # Safety
13///
14/// The pointers should be valid.
15#[no_mangle]
16pub unsafe extern "C" fn symt_new(new_struct: *mut *const CSymbolTable) -> RUSTFST_FFI_RESULT {
17    wrap(|| {
18        let table = Arc::new(SymbolTable::new());
19        let raw_ptr = CSymbolTable(table).into_raw_pointer();
20        unsafe { *new_struct = raw_ptr };
21        Ok(())
22    })
23}
24
25/// # Safety
26///
27/// The pointers should be valid.
28#[no_mangle]
29pub unsafe extern "C" fn symt_add_symbol(
30    symt: *mut CSymbolTable,
31    symbol: *const libc::c_char,
32    integer_key: *mut libc::size_t,
33) -> RUSTFST_FFI_RESULT {
34    wrap(|| {
35        let symt = get_mut!(CSymbolTable, symt);
36        let symbol: String = unsafe { CStr::from_ptr(symbol) }.as_rust()?;
37        let res = Arc::get_mut(symt)
38            .ok_or_else(|| anyhow!("Could not get a mutable reference to the symbol table"))?
39            .add_symbol(&symbol);
40        unsafe { *integer_key = res as libc::size_t };
41        Ok(())
42    })
43}
44
45/// # Safety
46///
47/// The pointers should be valid.
48#[no_mangle]
49pub unsafe extern "C" fn symt_add_table(
50    symt: *mut CSymbolTable,
51    other_symt: *const CSymbolTable,
52) -> RUSTFST_FFI_RESULT {
53    wrap(|| {
54        let symt = get_mut!(CSymbolTable, symt);
55        let other_symt = get!(CSymbolTable, other_symt);
56        Arc::get_mut(symt)
57            .ok_or_else(|| anyhow!("Could not get a mutable reference to the symbol table"))?
58            .add_table(other_symt);
59        Ok(())
60    })
61}
62
63/// # Safety
64///
65/// The pointers should be valid.
66#[no_mangle]
67pub unsafe extern "C" fn symt_find_index(
68    symt: *const CSymbolTable,
69    key: CStateId,
70    symbol: *mut *const libc::c_char,
71) -> RUSTFST_FFI_RESULT {
72    wrap(|| {
73        let symt = get!(CSymbolTable, symt);
74        let found_symbol = symt
75            .get_symbol(key)
76            .ok_or_else(|| format_err!("No symbol found at index:{}", key as i32))?;
77        unsafe {
78            *symbol = CString::c_repr_of(found_symbol.to_string())?.into_raw_pointer()
79                as *const libc::c_char
80        };
81        Ok(())
82    })
83}
84
85/// # Safety
86///
87/// The pointers should be valid.
88#[no_mangle]
89pub unsafe extern "C" fn symt_find_symbol(
90    symt: *const CSymbolTable,
91    symbol: *const libc::c_char,
92    key: *mut libc::size_t,
93) -> RUSTFST_FFI_RESULT {
94    wrap(|| {
95        let symt = get!(CSymbolTable, symt);
96        let symbol = unsafe { CStr::from_ptr(symbol) }.as_rust()?;
97        let res = symt
98            .get_label(&symbol)
99            .ok_or_else(|| format_err!("No symbol `{}` found", symbol))?;
100        unsafe { *key = res as libc::size_t };
101        Ok(())
102    })
103}
104
105/// # Safety
106///
107/// The pointers should be valid.
108#[no_mangle]
109pub unsafe extern "C" fn symt_from_path(
110    table_ptr: *mut *const CSymbolTable,
111    path_ptr: *const libc::c_char,
112    binary: *const libc::size_t,
113) -> RUSTFST_FFI_RESULT {
114    wrap(|| {
115        let path = unsafe { CStr::from_ptr(path_ptr) }.as_rust()?;
116        let binary = binary as i32 != 0;
117        let symb = if binary {
118            SymbolTable::read(&path)?
119        } else {
120            SymbolTable::read_text(&path)?
121        };
122        let raw_ptr = CSymbolTable(Arc::new(symb)).into_raw_pointer();
123        unsafe { *table_ptr = raw_ptr };
124        Ok(())
125    })
126}
127
128/// # Safety
129///
130/// The pointers should be valid.
131#[no_mangle]
132pub unsafe extern "C" fn symt_write_file(
133    symt: *const CSymbolTable,
134    path_ptr: *const libc::c_char,
135    binary: *const libc::size_t,
136) -> RUSTFST_FFI_RESULT {
137    wrap(|| {
138        let symt = get!(CSymbolTable, symt);
139        let path = unsafe { CStr::from_ptr(path_ptr) }.as_rust()?;
140        let binary = binary as i32 != 0;
141        if binary {
142            symt.write(&path)?
143        } else {
144            symt.write_text(&path)?
145        };
146
147        Ok(())
148    })
149}
150
151/// # Safety
152///
153/// The pointers should be valid.
154#[no_mangle]
155pub unsafe extern "C" fn symt_member_index(
156    symt: *const CSymbolTable,
157    key: CStateId,
158    is_present: *mut libc::size_t,
159) -> RUSTFST_FFI_RESULT {
160    wrap(|| {
161        let symt = get!(CSymbolTable, symt);
162        let res = symt.contains_label(key);
163        unsafe { *is_present = res as libc::size_t };
164        Ok(())
165    })
166}
167
168/// # Safety
169///
170/// The pointers should be valid.
171#[no_mangle]
172pub unsafe extern "C" fn symt_member_symbol(
173    symt: *const CSymbolTable,
174    symbol: *const libc::c_char,
175    is_present: *mut libc::size_t,
176) -> RUSTFST_FFI_RESULT {
177    wrap(|| {
178        let symt = get!(CSymbolTable, symt);
179        let symbol = unsafe { CStr::from_ptr(symbol) }.as_rust()?;
180        let res = symt.contains_symbol(symbol);
181        unsafe { *is_present = res as libc::size_t };
182        Ok(())
183    })
184}
185
186/// # Safety
187///
188/// The pointers should be valid.
189#[no_mangle]
190pub unsafe extern "C" fn symt_num_symbols(
191    symt: *const CSymbolTable,
192    num_symbols: *mut libc::size_t,
193) -> RUSTFST_FFI_RESULT {
194    wrap(|| {
195        let symt = get!(CSymbolTable, symt);
196        unsafe { *num_symbols = symt.len() as libc::size_t };
197        Ok(())
198    })
199}
200
201/// # Safety
202///
203/// The pointers should be valid.
204#[no_mangle]
205pub unsafe extern "C" fn symt_copy(
206    symt: *const CSymbolTable,
207    cloned_symt: *mut *const CSymbolTable,
208) -> RUSTFST_FFI_RESULT {
209    wrap(|| {
210        let symt = get!(CSymbolTable, symt);
211        let clone = Arc::new(SymbolTable::clone(symt));
212        let raw_ptr = CSymbolTable(clone).into_raw_pointer();
213        unsafe { *cloned_symt = raw_ptr };
214        Ok(())
215    })
216}
217
218/// # Safety
219///
220/// The pointers should be valid.
221#[no_mangle]
222pub unsafe fn symt_equals(
223    symt: *const CSymbolTable,
224    other_symt: *const CSymbolTable,
225    is_equal: *mut libc::size_t,
226) -> RUSTFST_FFI_RESULT {
227    wrap(|| {
228        let symt = get!(CSymbolTable, symt);
229        let other_symt = get!(CSymbolTable, other_symt);
230        let res = symt.eq(other_symt);
231        unsafe { *is_equal = res as usize }
232        Ok(())
233    })
234}
235
236/// drop impl
237/// # Safety
238///
239/// The pointers should be valid.
240#[no_mangle]
241pub unsafe extern "C" fn symt_destroy(symt_ptr: *mut CSymbolTable) -> RUSTFST_FFI_RESULT {
242    wrap(|| {
243        if symt_ptr.is_null() {
244            return Ok(());
245        }
246
247        drop(unsafe { Box::from_raw(symt_ptr) });
248        Ok(())
249    })
250}