use std::fs::File; use std::io::Read; use std::path::Path; // TODO: Make this work on only a predetermined size of a buffer. /// Stores some input and allows it to be /// read on a character by character basis. /// pub struct Reader { /// The current position in the buffer. position: usize, /// The buffer of the input data to be read. buffer: Vec } impl Reader { /// Create a new empty Reader. pub fn new() -> Reader { Reader { position: 0usize, buffer: Vec::new(), } } /// Create a new reader from a File. pub fn from_file(filepath: F) -> Reader where F: AsRef { let mut reader: Reader; // Create a new Reader and load the data // for it from the file at the given filepath. reader = Reader::new(); reader.load_from_file(filepath); reader } /// Create a new reader from a String. pub fn from_string(data: String) -> Reader { let mut reader: Reader; // Create a new Reader and load the data to it. reader = Reader::new(); reader.load_from_string(data); reader } /// Reset the Reader back to the starting position. pub fn reset(&mut self) { // Move back to the start of the buffer. self.position = 0usize; } /// Clear the Reader of all data. pub fn clear(&mut self) { self.buffer = Vec::new(); self.reset(); } /// Clears the Reader and sets it to read from a File. pub fn load_from_file(&mut self, filepath: F) where F: AsRef { let mut data: String; // Open the file for reading and load the // data into a String that will be parsed. data = String::new(); match File::open(filepath.as_ref()) { Ok(mut file) => { match file.read_to_string(&mut data) { Ok(bytes_read) => { info!("{} bytes read from {:?}", bytes_read, filepath.as_ref()); } Err(error) => { error!("{}", error); } } } Err(error) => { error!("{}", error); } } // Load the String read from the file. self.load_from_string(data); } /// Clears the Reader and sets it to read from the given data. pub fn load_from_string(&mut self, data: String) { // Clear the Reader. self.clear(); // Parse the String that the reader is // reading from as a set of characters // in the Reader's buffer. for character in data.chars() { self.buffer.push(character); } } /// Get the current character. pub fn get_char(&self) -> Result { // Make sure we are not at the end of the buffer. if self.is_eob() == false { // Return the character at the current position. Ok(self.buffer[self.position]) } else { // There was an error. Err("Unable to read character. \ No characters left in the input buffer.") } } /// Get the current character and move the /// Reader on to the next character. pub fn consume_char(&mut self) -> Result { let character: char; // Get the current character and move the position // in the buffer forward. character = try!(self.get_char()); self.position += 1; // Return the character that was retrieved. Ok(character) } /// Get a line of text from the current character to the next /// newline character, including the current character. pub fn get_line(&mut self) -> Result { let mut index: usize; let mut buffer: String; // Create a new buffer to hold the line created. buffer = String::new(); // Now get the current position the reader is at. index = self.position; while index < self.buffer.len() && self.buffer[index] != '\n' { buffer.push(self.buffer[index]); index += 1; } // Read the newline character if the reader did not run out of buffer. if index < self.buffer.len() && self.buffer[index] == '\n' { buffer.push(self.buffer[index]); } // Return the buffer of characters that was created. Ok(buffer) } /// Get a line of text from the current character to the next /// newline character, including the current character and newline. /// This will consume all the characters and move the position /// of the reader. pub fn consume_line(&mut self) -> Result { let mut continue_consuming: bool; let mut current_char: char; let mut buffer: String; // Create a new buffer to hold the line created. buffer = String::new(); // Consume all the characters of the line // and add them to the buffer. continue_consuming = true; while continue_consuming == true { current_char = try!(self.consume_char()); buffer.push(current_char); if current_char == '\n' { continue_consuming = false; } } // Return the buffer of characters that was created. Ok(buffer) } /// Check to see if we have reached the end of the buffer. pub fn is_eob(&self) -> bool { self.position >= self.buffer.len() } }