md 0.0.1

A pure-Rust Markdown parser implementation, CommonMark-compatible
use std::cell::Cell;

pub trait CellOps<T> {
    fn modify(&self, f: |T| -> T);
}

impl<T: Copy> CellOps<T> for Cell<T> {
    fn modify(&self, f: |T| -> T) {
        self.set(f(self.get()));
    }
}

pub trait CharOps {
    fn is_emphasis(self) -> bool;
    fn is_code(self) -> bool;
    fn is_space(self) -> bool;
    fn is_numeric(self) -> bool;
}

impl CharOps for u8 {
    fn is_emphasis(self) -> bool {
        self == b'*' || self == b'_'
    }

    fn is_code(self) -> bool {
        self == b'`'
    }

    fn is_space(self) -> bool {
        self == b' ' || self == b'\n'
    }

    fn is_numeric(self) -> bool {
        static DIGITS: &'static [u8] = b"0123456789";
        DIGITS.contains(&self)
    }
}

pub trait ByteMatcher {
    fn matches(&mut self, b: u8) -> bool;
}

impl<'a> ByteMatcher for |u8|:'a -> bool {
    #[inline]
    fn matches(&mut self, b: u8) -> bool { (*self)(b) }
}

impl ByteMatcher for u8 {
    #[inline]
    fn matches(&mut self, b: u8) -> bool { *self == b }
}

impl<'a> ByteMatcher for &'a [u8] {
    #[inline]
    fn matches(&mut self, b: u8) -> bool {
        self.iter().any(|& mut c| c.matches(b))
    }
}

pub trait ByteSliceOps<'a> {
    fn trim_left<M: ByteMatcher>(&self, m: M) -> &'a [u8];
    fn trim_right<M: ByteMatcher>(&self, m: M) -> &'a [u8];
    fn trim_left_one<M: ByteMatcher>(&self, m: M) -> &'a [u8];
    fn trim_right_one<M: ByteMatcher>(&self, m: M) -> &'a [u8];
}

static EMPTY_SLICE: &'static [u8] = &[];

impl<'a> ByteSliceOps<'a> for &'a [u8] {
    fn trim_left<M: ByteMatcher>(&self, mut m: M) -> &'a [u8] {
        match self.iter().position(|&b| !m.matches(b)) {
            None => EMPTY_SLICE,
            Some(idx) => self.slice_from(idx)
        }
    }

    fn trim_right<M: ByteMatcher>(&self, mut m: M) -> &'a [u8] {
        match self.iter().rposition(|&b| !m.matches(b)) {
            None => EMPTY_SLICE,
            Some(idx) => self.slice_to(idx+1)
        }
    }

    #[inline]
    fn trim_left_one<M: ByteMatcher>(&self, mut m: M) -> &'a [u8] {
        match self.head() {
            Some(&c) => if m.matches(c) { self.slice_from(1) } else { *self },
            _ => *self
        }
    }

    #[inline]
    fn trim_right_one<M: ByteMatcher>(&self, mut m: M) -> &'a [u8] {
        match self.last() {
            Some(&c) => if m.matches(c) { self.slice_to(self.len()-1) } else { *self },
            _ => *self
        }
    }

}