rustfst_ffi/algorithms/
determinize.rs

1use anyhow::{anyhow, Result};
2
3use super::EnumConversionError;
4use crate::fst::CFst;
5use crate::{get, wrap, RUSTFST_FFI_RESULT};
6
7use ffi_convert::*;
8use rustfst::algorithms::determinize::{
9    determinize, determinize_with_config, DeterminizeConfig, DeterminizeType,
10};
11use rustfst::fst_impls::VectorFst;
12use rustfst::semirings::TropicalWeight;
13
14#[derive(RawPointerConverter)]
15pub struct CDeterminizeType(usize);
16
17impl AsRust<DeterminizeType> for CDeterminizeType {
18    fn as_rust(&self) -> Result<DeterminizeType, AsRustError> {
19        match self.0 {
20            0 => Ok(DeterminizeType::DeterminizeFunctional),
21            1 => Ok(DeterminizeType::DeterminizeNonFunctional),
22            2 => Ok(DeterminizeType::DeterminizeDisambiguate),
23            _ => Err(AsRustError::Other(Box::new(EnumConversionError {}))),
24        }
25    }
26}
27
28impl CDrop for CDeterminizeType {
29    fn do_drop(&mut self) -> Result<(), CDropError> {
30        Ok(())
31    }
32}
33
34impl CReprOf<DeterminizeType> for CDeterminizeType {
35    fn c_repr_of(value: DeterminizeType) -> Result<CDeterminizeType, CReprOfError> {
36        let variant = match value {
37            DeterminizeType::DeterminizeFunctional => 0,
38            DeterminizeType::DeterminizeNonFunctional => 1,
39            DeterminizeType::DeterminizeDisambiguate => 2,
40        };
41        Ok(CDeterminizeType(variant))
42    }
43}
44
45#[derive(AsRust, CReprOf, CDrop, RawPointerConverter)]
46#[target_type(DeterminizeConfig)]
47pub struct CDeterminizeConfig {
48    delta: f32,
49    det_type: CDeterminizeType,
50}
51
52/// # Safety
53///
54/// The pointers should be valid.
55#[no_mangle]
56pub unsafe extern "C" fn fst_determinize_config_new(
57    delta: libc::c_float,
58    det_type: libc::size_t,
59    config: *mut *const CDeterminizeConfig,
60) -> RUSTFST_FFI_RESULT {
61    wrap(|| {
62        let determinize_config = CDeterminizeConfig {
63            delta,
64            det_type: CDeterminizeType(det_type),
65        };
66        unsafe { *config = determinize_config.into_raw_pointer() };
67        Ok(())
68    })
69}
70
71/// # Safety
72///
73/// The pointers should be valid.
74#[no_mangle]
75pub unsafe extern "C" fn fst_determinize(
76    ptr: *const CFst,
77    det_fst: *mut *const CFst,
78) -> RUSTFST_FFI_RESULT {
79    wrap(|| {
80        let fst = get!(CFst, ptr);
81        let vec_fst: &VectorFst<TropicalWeight> = fst
82            .downcast_ref()
83            .ok_or_else(|| anyhow!("Could not downcast to vector FST"))?;
84        let fst: VectorFst<TropicalWeight> = determinize(vec_fst)?;
85        let fst_ptr = CFst(Box::new(fst)).into_raw_pointer();
86        unsafe { *det_fst = fst_ptr };
87        Ok(())
88    })
89}
90
91/// # Safety
92///
93/// The pointers should be valid.
94#[no_mangle]
95pub unsafe extern "C" fn fst_determinize_with_config(
96    ptr: *const CFst,
97    config: *const CDeterminizeConfig,
98    det_fst: *mut *const CFst,
99) -> RUSTFST_FFI_RESULT {
100    wrap(|| {
101        let fst = get!(CFst, ptr);
102        let vec_fst: &VectorFst<TropicalWeight> = fst
103            .downcast_ref()
104            .ok_or_else(|| anyhow!("Could not downcast to vector FST"))?;
105
106        let det_config = unsafe {
107            <CDeterminizeConfig as ffi_convert::RawBorrow<CDeterminizeConfig>>::raw_borrow(config)?
108        };
109        let fst: VectorFst<TropicalWeight> =
110            determinize_with_config(vec_fst, det_config.as_rust()?)?;
111        let fst_ptr = CFst(Box::new(fst)).into_raw_pointer();
112        unsafe { *det_fst = fst_ptr };
113        Ok(())
114    })
115}