chamkho 0.0.3

Thai word segmentation/breaking library and command line
Documentation
use std::fs::File;
use std::io::Read;
use std::path::Path;

#[allow(dead_code)]
pub enum Policy {
    Left, Right
}

pub struct Dict {
    wlst: Vec<Vec<char>>
}

impl Dict {
    pub fn default_path() -> &'static Path {
        Path::new(
            concat!(env!("CARGO_MANIFEST_DIR"),
                    "/data/tdict-std.txt"))
    }

    pub fn create<'a>(words: &Vec<String>) -> Result<Dict, &'a str> {
        Ok(Dict{wlst:words.iter().map(|w| w.chars().collect()).collect()})
    }

    pub fn load<'a>(path: &Path) -> Result<Dict, &'a str> {
        let mut f = match File::open(path) {
            Ok(f) => f,
            Err(_) => return Err("Cannot open dict")
        };
        let mut s = String::new();
        match f.read_to_string(&mut s) {
            Ok(_) => (),
            Err(_) => return Err("Cannot read dict")
        };
        let words = s.lines();
        let wlst: Vec<Vec<char>> = words.map(|w| w.chars().collect()).collect();
        Ok(Dict{wlst:wlst})
    }

    pub fn seek(&self, policy: Policy, _l: usize, _r: usize, offset: usize, ch: char) -> Option<usize> {
        let mut ans: usize = 0;
        let mut found = false;
        let mut m: usize;
        let mut l = _l as i64;
        let mut r = _r as i64;

        while l <= r {
            m = ((l + r) / 2) as usize;
            let w = &self.wlst[m];
            let wlen = w.len();
            if wlen <= offset {
                l = (m as i64) + 1;
            } else {
                let ch_ = w[offset];
                if ch_ < ch {
                    l = (m as i64) + 1;
                } else if ch_ > ch {
                    r = (m as i64) - 1;
                } else {
                    ans = m;
                    found = true;
                    match policy {
                        Policy::Left => r = (m as i64) - 1,
                        Policy::Right => l = (m as i64) + 1
                    }
                }
            }
        }
        if found {
            Some(ans)
        } else {
            None
        }
    }

    pub fn is_final(&self, len: usize, m: usize) -> bool {
        let w = &self.wlst[m];
        let wlen = w.len();
        wlen == len
    }

    pub fn r(&self) -> usize {
        self.wlst.len() - 1
    }
}