63 lines
2.0 KiB
Rust
63 lines
2.0 KiB
Rust
use std::{path::Path, fs::File, io::{self, BufRead, Read}};
|
|
use crate::game::Game;
|
|
|
|
/// An error when reading the file
|
|
#[derive(Debug)]
|
|
pub enum ReaderError {
|
|
FileAccessError,
|
|
ParseError,
|
|
}
|
|
|
|
|
|
/// Read the file at a given path. If all goes well, will return `Ok(game)`, with a game
|
|
/// initialised with that pattern. Can return errors for either file access or failed parsing.
|
|
pub fn read_game_at_path(path: &str) -> Result<Game, ReaderError> {
|
|
let path = Path::new(path);
|
|
let file = open_file(path)?;
|
|
read_game(file)
|
|
}
|
|
|
|
/// Read from any `impl Read`. If all goes well, will return `Ok<Game>` with a game
|
|
/// initialised with that pattern. Can return errors for failed parsing.
|
|
pub fn read_game(file: impl Read) -> Result<Game, ReaderError> {
|
|
let lines = io::BufReader::new(file).lines();
|
|
let mut game = Game::new();
|
|
let mut x_index = 0;
|
|
for line in lines {
|
|
if let Ok(ip) = line {
|
|
// Comment/metadata
|
|
if ip.starts_with("!") || ip.starts_with("#") {continue}
|
|
x_index += 1;
|
|
for (cell, y_index) in ip.chars().zip(0..) {
|
|
match cell {
|
|
// Live cell
|
|
'*' | 'O' => {game.flip_state((y_index, x_index));},
|
|
// Dead cell
|
|
'.' | ' ' => continue,
|
|
// Invalid character
|
|
_ => {return Err(ReaderError::ParseError);},
|
|
}
|
|
/*if cell == '*' || cell == 'O' {
|
|
// Live cell
|
|
game.flip_state((y_index, x_index));
|
|
} else if cell == '.' || cell == ' ' {
|
|
// Dead cell
|
|
continue
|
|
} else {
|
|
// Invalid character
|
|
return Err(ReaderError::ParseError);
|
|
}*/
|
|
}
|
|
}
|
|
}
|
|
Ok(game)
|
|
}
|
|
|
|
|
|
fn open_file(path: &Path) -> Result<File, ReaderError> {
|
|
match File::open(path) {
|
|
Ok(file) => Ok(file),
|
|
Err(_) => Err(ReaderError::FileAccessError),
|
|
}
|
|
}
|