pocketsphinx 0.6.0

Rust wrapper for libpocketsphinx
Documentation
use bindings;

use std;
use std::ffi::{CStr, CString, OsStr};
use libc::c_int;

use std::os::unix::ffi::OsStrExt;

use super::PsDecoder;
use super::{Error, Result};

pub struct Searches<'a> {
    raw: *mut bindings::ps_search_iter_t,
    _marker: std::marker::PhantomData<&'a str>,
}

impl<'a> Searches<'a> {
    pub fn new(raw_ps: *const bindings::ps_decoder_t) -> Self {
        let iter = unsafe { bindings::ps_search_iter(raw_ps) };
        Searches { raw: iter, _marker: std::marker::PhantomData }
    }
}

impl<'a> Drop for Searches<'a> {
    fn drop(&mut self) {
        if !self.raw.is_null() {
            unsafe { bindings::ps_search_iter_free(self.raw) };
        }
    }
}

impl<'a> Iterator for Searches<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<Self::Item> {
        if self.raw.is_null() {
            None
        } else {
            let item = unsafe { bindings::ps_search_iter_val(self.raw) };
            self.raw = unsafe { bindings::ps_search_iter_next(self.raw) };
            Some(unsafe { CStr::from_ptr(item).to_str().unwrap() })
        }
    }
}

pub trait PsDecoderSearchExt {
    fn set_search(&mut self, name: &str) -> Result<()>;
    fn get_search(&self) -> Option<&str>;
    fn unset_search(&mut self, name: &str) -> Result<()>;
    fn set_lm_file(&mut self, name: &str, path: &OsStr) -> Result<()>;
    fn set_jsgf_file(&mut self, name: &str, path: &OsStr) -> Result<()>;
    fn set_jsgf_string(&mut self, name: &str, jsgf_string: &str) -> Result<()>;
    fn ps_set_kws(&mut self, name: &str, keyfile: &OsStr) -> Result<()>;
    fn set_keyphrase(&mut self, name: &str, keyphrase: &str) -> Result<()>;
    fn set_allphone_file(&mut self, name: &str, path: &OsStr) -> Result<()>;
}

fn check_res(res: c_int) -> Result<()> {
    match res {
        0 => Ok(()),
        -1 => Err(Error),
        _ => unreachable!(),
    }
}

impl PsDecoderSearchExt for PsDecoder {
    fn set_search(&mut self, name: &str) -> Result<()> {
        let name_cstr = CString::new(name).unwrap();
        check_res(unsafe { bindings::ps_set_search(self.raw, name_cstr.as_ptr()) })
    }

    fn get_search(&self) -> Option<&str> {
        let name_c = unsafe { bindings::ps_get_search(self.raw) };
        if name_c.is_null() {
            None
        } else {
            Some(unsafe { CStr::from_ptr(name_c) }.to_str().unwrap())
        }
    }

    fn unset_search(&mut self, name: &str) -> Result<()> {
        let name_cstr = CString::new(name).unwrap();
        check_res(unsafe { bindings::ps_unset_search(self.raw, name_cstr.as_ptr()) })
    }

    fn set_lm_file(&mut self, name: &str, path: &OsStr) -> Result<()> {
        let name_c = CString::new(name).unwrap();
        let path_c = CString::new(path.as_bytes()).unwrap();
        check_res(unsafe { bindings::ps_set_lm_file(self.raw, name_c.as_ptr(), path_c.as_ptr()) })
    }

    fn set_jsgf_file(&mut self, name: &str, path: &OsStr) -> Result<()> {
        let name_c = CString::new(name).unwrap();
        let path_c = CString::new(path.as_bytes()).unwrap();
        check_res(unsafe {
            bindings::ps_set_jsgf_file(self.raw, name_c.as_ptr(), path_c.as_ptr())
        })
    }

    fn set_jsgf_string(&mut self, name: &str, jsgf_string: &str) -> Result<()> {
        let name_c = CString::new(name).unwrap();
        let jsgf_string_c = CString::new(jsgf_string).unwrap();
        check_res(unsafe {
            bindings::ps_set_jsgf_string(self.raw, name_c.as_ptr(), jsgf_string_c.as_ptr())
        })
    }

    fn ps_set_kws(&mut self, name: &str, keyfile: &OsStr) -> Result<()> {
        let name_c = CString::new(name).unwrap();
        let keyfile_c = CString::new(keyfile.as_bytes()).unwrap();
        check_res(unsafe {
            bindings::ps_set_kws(self.raw, name_c.as_ptr(), keyfile_c.as_ptr())
        })
    }
    fn set_keyphrase(&mut self, name: &str, keyphrase: &str) -> Result<()> {
        let name_c = CString::new(name).unwrap();
        let keyphrase_c = CString::new(keyphrase).unwrap();
        check_res(unsafe {
            bindings::ps_set_keyphrase(self.raw, name_c.as_ptr(), keyphrase_c.as_ptr())
        })
    }

    fn set_allphone_file(&mut self, name: &str, path: &OsStr) -> Result<()> {
        let name_c = CString::new(name).unwrap();
        let path_c = CString::new(path.as_bytes()).unwrap();
        check_res(unsafe {
            bindings::ps_set_allphone_file(self.raw, name_c.as_ptr(), path_c.as_ptr())
        })
    }
}