use libedit_sys::*;
use std::ffi::{CStr, CString};
use std::ptr;
use crate::error::{Error, Result};
pub struct Tokenizer {
inner: *mut libedit_sys::Tokenizer,
}
impl Tokenizer {
pub fn new(separators: Option<&str>) -> Result<Self> {
let sep = match separators {
Some(s) => Some(CString::new(s)?),
None => None,
};
let inner = unsafe {
match &sep {
Some(s) => tok_init(s.as_ptr()),
None => tok_init(ptr::null()),
}
};
if inner.is_null() {
return Err(Error::operation(0, -1));
}
Ok(Tokenizer { inner })
}
pub fn tokenize(&mut self, input: impl AsRef<str>) -> Result<Vec<String>> {
let c_input = CString::new(input.as_ref())?;
let mut argc: i32 = 0;
let mut argv: *mut *const std::os::raw::c_char = ptr::null_mut();
let ret = unsafe { tok_str(self.inner, c_input.as_ptr(), &mut argc, &mut argv) };
if ret != 0 {
return Err(Error::operation(0, ret));
}
let mut words = Vec::with_capacity(argc as usize);
for i in 0..argc {
let word = unsafe { CStr::from_ptr(*argv.offset(i as isize)) };
words.push(word.to_string_lossy().into_owned());
}
Ok(words)
}
pub fn reset(&mut self) {
unsafe { tok_reset(self.inner) };
}
}
impl Drop for Tokenizer {
fn drop(&mut self) {
unsafe { tok_end(self.inner) };
}
}