rustfst_ffi/algorithms/
shortest_path.rs

1use anyhow::anyhow;
2
3use crate::fst::CFst;
4use crate::{get, wrap, RUSTFST_FFI_RESULT};
5
6use ffi_convert::*;
7use rustfst::algorithms::{shortest_path, shortest_path_with_config, ShortestPathConfig};
8use rustfst::fst_impls::VectorFst;
9use rustfst::semirings::TropicalWeight;
10
11#[derive(AsRust, CReprOf, CDrop, RawPointerConverter)]
12#[target_type(ShortestPathConfig)]
13pub struct CShortestPathConfig {
14    delta: f32,
15    nshortest: usize,
16    unique: bool,
17}
18
19/// # Safety
20///
21/// The pointers should be valid.
22#[no_mangle]
23pub unsafe extern "C" fn fst_shortest_path_config_new(
24    delta: libc::c_float,
25    nshortest: libc::size_t,
26    unique: bool,
27    ptr: *mut *const CShortestPathConfig,
28) -> RUSTFST_FFI_RESULT {
29    wrap(|| {
30        let config = CShortestPathConfig {
31            delta,
32            nshortest,
33            unique,
34        };
35        unsafe { *ptr = config.into_raw_pointer() };
36        Ok(())
37    })
38}
39
40/// # Safety
41///
42/// The pointers should be valid.
43#[no_mangle]
44pub unsafe extern "C" fn fst_shortest_path(
45    ptr: *const CFst,
46    res_fst: *mut *const CFst,
47) -> RUSTFST_FFI_RESULT {
48    wrap(|| {
49        let fst = get!(CFst, ptr);
50        let vec_fst: &VectorFst<TropicalWeight> = fst
51            .downcast_ref()
52            .ok_or_else(|| anyhow!("Could not downcast to vector FST"))?;
53        let res: VectorFst<TropicalWeight> = shortest_path(vec_fst)?;
54        unsafe { *res_fst = CFst(Box::new(res)).into_raw_pointer() };
55        Ok(())
56    })
57}
58
59/// # Safety
60///
61/// The pointers should be valid.
62#[no_mangle]
63pub unsafe extern "C" fn fst_shortest_path_with_config(
64    ptr: *const CFst,
65    config: *const CShortestPathConfig,
66    res_fst: *mut *const CFst,
67) -> RUSTFST_FFI_RESULT {
68    wrap(|| {
69        let fst = get!(CFst, ptr);
70        let vec_fst: &VectorFst<TropicalWeight> = fst
71            .downcast_ref()
72            .ok_or_else(|| anyhow!("Could not downcast to vector FST"))?;
73
74        let config = unsafe {
75            <CShortestPathConfig as ffi_convert::RawBorrow<CShortestPathConfig>>::raw_borrow(
76                config,
77            )?
78        };
79        let res: VectorFst<TropicalWeight> = shortest_path_with_config(vec_fst, config.as_rust()?)?;
80        unsafe { *res_fst = CFst(Box::new(res)).into_raw_pointer() };
81        Ok(())
82    })
83}