use super::ffi;
use std::ffi::CStr;
use std::marker::PhantomData;
use std::ptr::NonNull;
#[derive(Clone, Copy)]
pub struct Node<'a> {
inner: NonNull<ffi::mecab_node_t>,
_marker: PhantomData<&'a ffi::mecab_node_t>,
}
impl<'a> Node<'a> {
pub fn as_ptr(&self) -> *mut ffi::mecab_node_t {
self.inner.as_ptr()
}
pub(crate) fn from_ptr(inner: *mut ffi::mecab_node_t) -> Option<Self> {
NonNull::new(inner).map(|inner| Node {
inner,
_marker: PhantomData,
})
}
pub fn next(self) -> Option<Self> {
unsafe {
let node = (*self.as_ptr()).next;
Node::from_ptr(node)
}
}
pub fn prev(self) -> Option<Self> {
unsafe {
let node = (*self.as_ptr()).prev;
Node::from_ptr(node)
}
}
pub fn id(self) -> u32 {
unsafe { (*self.as_ptr()).id }
}
pub fn feature(self) -> &'a str {
unsafe {
let ptr = (*self.as_ptr()).feature;
let s = CStr::from_ptr(ptr);
std::str::from_utf8_unchecked(s.to_bytes())
}
}
pub fn surface(self) -> &'a str {
unsafe {
let ptr = (*self.as_ptr()).surface;
let len = (*self.as_ptr()).length;
std::str::from_utf8_unchecked(std::slice::from_raw_parts(
ptr as *const u8,
len as usize,
))
}
}
pub fn kind(self) -> NodeKind {
use ffi::{MECAB_BOS_NODE, MECAB_EON_NODE, MECAB_EOS_NODE, MECAB_NOR_NODE, MECAB_UNK_NODE};
unsafe {
let kind = (*self.as_ptr()).stat as u32;
if kind == MECAB_BOS_NODE {
NodeKind::Bos
} else if kind == MECAB_EOS_NODE {
NodeKind::Eos
} else if kind == MECAB_UNK_NODE {
NodeKind::Unk
} else if kind == MECAB_EON_NODE {
NodeKind::EoNbest
} else {
debug_assert_eq!(kind, MECAB_NOR_NODE);
NodeKind::Normal
}
}
}
pub fn lc_attr(self) -> LcAttr {
unsafe { LcAttr((*self.as_ptr()).lcAttr) }
}
pub fn rc_attr(self) -> RcAttr {
unsafe { RcAttr((*self.as_ptr()).rcAttr) }
}
pub fn pos_id(self) -> u16 {
unsafe { (*self.as_ptr()).posid }
}
pub fn char_type(self) -> u8 {
unsafe { (*self.as_ptr()).char_type }
}
pub fn is_best(self) -> bool {
unsafe { (*self.as_ptr()).isbest == 1 }
}
pub fn alpha(self) -> f32 {
unsafe { (*self.as_ptr()).alpha }
}
pub fn beta(self) -> f32 {
unsafe { (*self.as_ptr()).beta }
}
pub fn prob(self) -> f32 {
unsafe { (*self.as_ptr()).prob }
}
pub fn wcost(self) -> i16 {
unsafe { (*self.as_ptr()).wcost }
}
pub fn cost(self) -> i64 {
unsafe { (*self.as_ptr()).cost }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum NodeKind {
Bos,
Eos,
Unk,
EoNbest,
Normal,
}
impl NodeKind {
pub fn is_bos(self) -> bool {
self == Self::Bos
}
pub fn is_eos(self) -> bool {
self == Self::Eos
}
}
pub struct NodeCursor<'a> {
pub(crate) curr: Option<Node<'a>>,
}
impl<'a> NodeCursor<'a> {
pub fn move_next(&mut self) {
if let Some(curr) = self.curr {
self.curr = curr.next();
}
}
pub fn move_prev(&mut self) {
if let Some(curr) = self.curr {
self.curr = curr.prev();
}
}
pub fn curr(&self) -> Option<Node<'a>> {
self.curr
}
}
impl<'a> Iterator for NodeCursor<'a> {
type Item = Node<'a>;
fn next(&mut self) -> Option<Self::Item> {
let res = self.curr?;
self.move_next();
Some(res)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LcAttr(u16);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RcAttr(u16);
impl LcAttr {
pub fn from_raw(attr: u16) -> Self {
Self(attr)
}
pub fn to_raw(self) -> u16 {
self.0
}
}
impl RcAttr {
pub fn from_raw(attr: u16) -> Self {
Self(attr)
}
pub fn to_raw(self) -> u16 {
self.0
}
}