1#![allow(clippy::single_component_path_imports)]
2
3pub mod algorithms;
4pub mod fst;
5pub mod iterators;
6pub mod string_path;
7pub mod string_paths_iterator;
8pub mod symbol_table;
9pub mod tr;
10pub mod trs;
11
12use std::cell::RefCell;
13use std::ffi::CString;
14use std::sync::Arc;
15
16use anyhow::Result;
17use ffi_convert::{CReprOf, RawPointerConverter};
18
19#[cfg(feature = "rustfst-state-label-u32")]
20pub type CLabel = libc::c_uint;
21#[cfg(not(feature = "rustfst-state-label-u32"))]
22pub type CLabel = libc::size_t;
23
24#[cfg(feature = "rustfst-state-label-u32")]
25pub type CStateId = libc::c_uint;
26#[cfg(not(feature = "rustfst-state-label-u32"))]
27pub type CStateId = libc::size_t;
28
29#[repr(C)]
30#[allow(non_camel_case_types)]
31#[derive(Debug, PartialEq, Eq)]
32pub enum RUSTFST_FFI_RESULT {
33 RUSTFST_FFI_RESULT_OK = 0,
35 RUSTFST_FFI_RESULT_KO = 1,
37}
38
39thread_local! {
40 pub(crate) static LAST_ERROR: RefCell<Option<String>> = const { RefCell::new(None) };
41}
42
43pub fn wrap<F: FnOnce() -> Result<()>>(func: F) -> RUSTFST_FFI_RESULT {
44 match func() {
45 Ok(_) => RUSTFST_FFI_RESULT::RUSTFST_FFI_RESULT_OK,
46 Err(e) => {
47 let msg = format!("{:#?}", e);
48 if std::env::var("AMSTRAM_FFI_ERROR_STDERR").is_ok() {
49 eprintln!("{}", msg);
50 }
51 LAST_ERROR.with(|p| *p.borrow_mut() = Some(msg));
52 RUSTFST_FFI_RESULT::RUSTFST_FFI_RESULT_KO
53 }
54 }
55}
56
57#[no_mangle]
61pub unsafe extern "C" fn rustfst_ffi_get_last_error(
62 error: *mut *mut ::libc::c_char,
63) -> RUSTFST_FFI_RESULT {
64 wrap(move || {
65 LAST_ERROR.with(|msg| {
66 let string = msg
67 .borrow_mut()
68 .take()
69 .unwrap_or_else(|| "No error message".to_string());
70 let result: *const ::libc::c_char =
71 std::ffi::CString::c_repr_of(string)?.into_raw_pointer();
72 unsafe { *error = result as _ }
73 Ok(())
74 })
75 })
76}
77
78#[allow(clippy::missing_safety_doc)]
79#[no_mangle]
80pub unsafe extern "C" fn rustfst_destroy_string(string: *mut libc::c_char) -> RUSTFST_FFI_RESULT {
81 wrap(|| {
82 CString::drop_raw_pointer(string)?;
83 Ok(())
84 })
85}
86
87macro_rules! get_mut {
88 ($typ:ty,$opaque:ident) => {{
89 &mut unsafe { <$typ as ffi_convert::RawBorrowMut<$typ>>::raw_borrow_mut($opaque) }?.0
90 }};
91}
92
93macro_rules! get {
94 ($typ:ty,$opaque:ident) => {{
95 &unsafe { <$typ as ffi_convert::RawBorrow<$typ>>::raw_borrow($opaque) }?.0
96 }};
97}
98
99use crate::symbol_table::CSymbolTable;
100pub(crate) use get;
101pub(crate) use get_mut;
102use rustfst::SymbolTable;
103
104pub(crate) fn get_symt(symt: *const CSymbolTable) -> Result<Option<&'static Arc<SymbolTable>>> {
105 if symt.is_null() {
106 return Ok(None);
107 }
108 Ok(Some(get!(CSymbolTable, symt)))
109}