ferret 1.1.1

A trigram-based tool for detecting similarity in groups of text documents or program code.
Documentation
//! Provides access to a stream of characters, one-by-one.

/// The CharDrip struct stores a vector of characters, and holds a current 
/// position within that vector. Methods are provided to read the next 
/// character, or unread a character previously read.
pub struct CharDrip {
    chars : Vec<char>,
    position : usize,
}

impl CharDrip {

    /// Creates an instance of CharDrip from a vector of characters.
    pub fn new (chars: Vec<char>) -> CharDrip {
        CharDrip {chars: chars, position: 0}
    }

    /// Returns the next available character, or None if there are no 
    /// more characters available.
    pub fn read (&mut self) -> Option<char> {
        if self.position >= self.chars.len () {
            return None;
        } else {
            self.position += 1;
            return Some(self.chars[self.position-1]);
        }
    }

    /// Resets the current position so the last read character is treated
    /// as unread, and available for reading again.
    pub fn unread (&mut self) {
        debug_assert! (self.position > 0);
        if self.position > 0 {
            self.position -= 1;
        }
    }
}

/// Moves past any whitespace characters, returning string with those blanks
pub fn skip_blanks (dripper : &mut CharDrip) -> String {
    let mut blanks = String::from("");

    loop {
        match dripper.read () {
            Some(c) => {
                if c.is_ascii_whitespace () {
                    blanks.push (c);
                } else {
                    dripper.unread ();
                    return blanks;
                }
            },
            None => {
                return blanks;
            },
        }
    }
}

/// Moves past non alphabetic characters, returning string with the nonalphabetic chars
pub fn skip_non_alphabetic (dripper : &mut CharDrip) -> String {
    let mut ignored = String::from("");

    loop { 
        match dripper.read () {
            Some(c) => {
                if c.is_alphabetic () {
                    dripper.unread ();
                    return ignored;
                } else {
                    ignored.push (c);
                }
            },
            None => {
                return ignored;
            },
        }
    }
}