rustfst_ffi/
string_paths_iterator.rs

1use std::iter::Peekable;
2
3use anyhow::{anyhow, Result};
4use ffi_convert::{RawPointerConverter, UnexpectedNullPointerError};
5
6use rustfst::fst_impls::VectorFst;
7use rustfst::prelude::{Fst, StringPathsIterator};
8use rustfst::semirings::TropicalWeight;
9
10use crate::fst::as_fst;
11use crate::fst::CFst;
12use crate::string_path::CStringPath;
13use crate::{get, get_mut, wrap, RUSTFST_FFI_RESULT};
14
15pub struct CStringPathsIterator<'a>(
16    pub(crate) Peekable<StringPathsIterator<'a, TropicalWeight, VectorFst<TropicalWeight>>>,
17);
18
19impl<'a> RawPointerConverter<CStringPathsIterator<'a>> for CStringPathsIterator<'a> {
20    fn into_raw_pointer(self) -> *const CStringPathsIterator<'a> {
21        Box::into_raw(Box::new(self)) as _
22    }
23    fn into_raw_pointer_mut(self) -> *mut CStringPathsIterator<'a> {
24        Box::into_raw(Box::new(self))
25    }
26
27    unsafe fn from_raw_pointer(
28        input: *const CStringPathsIterator<'a>,
29    ) -> Result<Self, UnexpectedNullPointerError> {
30        if input.is_null() {
31            Err(UnexpectedNullPointerError)
32        } else {
33            Ok(*Box::from_raw(input as _))
34        }
35    }
36
37    unsafe fn from_raw_pointer_mut(
38        input: *mut CStringPathsIterator<'a>,
39    ) -> Result<Self, UnexpectedNullPointerError> {
40        if input.is_null() {
41            Err(UnexpectedNullPointerError)
42        } else {
43            Ok(*Box::from_raw(input))
44        }
45    }
46}
47
48/// # Safety
49///
50/// The pointers should be valid.
51#[no_mangle]
52pub unsafe extern "C" fn string_paths_iterator_new(
53    fst: *const CFst,
54    res_iterator: *mut *const CStringPathsIterator,
55) -> RUSTFST_FFI_RESULT {
56    wrap(|| {
57        let fst = get!(CFst, fst);
58        let fst: &VectorFst<_> = as_fst!(VectorFst<TropicalWeight>, fst);
59        let it = fst.string_paths_iter()?.peekable();
60        let raw_pointer = CStringPathsIterator(it).into_raw_pointer();
61        unsafe { *res_iterator = raw_pointer };
62        Ok(())
63    })
64}
65
66/// # Safety
67///
68/// The pointers should be valid.
69#[no_mangle]
70pub unsafe extern "C" fn string_paths_iterator_next(
71    iter_ptr: *mut CStringPathsIterator,
72    string_path_ptr: *mut *const CStringPath,
73) -> RUSTFST_FFI_RESULT {
74    wrap(|| {
75        let string_paths_iter = get_mut!(CStringPathsIterator, iter_ptr);
76        string_paths_iter
77            .next()
78            .map(|string_path| {
79                let ctr = CStringPath(string_path).into_raw_pointer();
80                unsafe { *string_path_ptr = ctr };
81                Ok(())
82            })
83            .unwrap_or_else(|| -> Result<()> {
84                unsafe { *string_path_ptr = std::ptr::null_mut() };
85                Ok(())
86            })?;
87        Ok(())
88    })
89}
90
91/// # Safety
92///
93/// The pointers should be valid.
94#[no_mangle]
95pub unsafe extern "C" fn string_paths_iterator_done(
96    iter_ptr: *mut CStringPathsIterator,
97    done: *mut libc::size_t,
98) -> RUSTFST_FFI_RESULT {
99    wrap(|| {
100        let string_paths_iter = get_mut!(CStringPathsIterator, iter_ptr);
101        let res = string_paths_iter.peek().is_none();
102        unsafe { *done = res as libc::size_t };
103        Ok(())
104    })
105}
106
107/// # Safety
108///
109/// The pointers should be valid.
110#[no_mangle]
111pub unsafe extern "C" fn string_paths_iterator_destroy(
112    iter_ptr: *mut CStringPathsIterator,
113) -> RUSTFST_FFI_RESULT {
114    wrap(|| {
115        if iter_ptr.is_null() {
116            return Ok(());
117        }
118
119        drop(unsafe { Box::from_raw(iter_ptr) });
120        Ok(())
121    })
122}