1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use vec_map::VecMap;
use std::io::Read;
use std::fs::File;
use core::Program;
use parse::{parse_program, ProgramErrors};
pub type Save = VecMap<Program>;
pub type SaveErrors = VecMap<ProgramErrors>;
pub enum LoadSaveError {
ParseFailed(SaveErrors),
LoadFailed,
}
use self::LoadSaveError::*;
pub fn load_save(filename: &str) -> Result<Save, LoadSaveError> {
match File::open(filename) {
Ok(mut file) => {
let mut src = String::new();
match file.read_to_string(&mut src) {
Ok(_) => match parse_save(&src) {
Ok(prog) => Ok(prog),
Err(errs) => Err(ParseFailed(errs)),
},
Err(_) => Err(LoadFailed),
}
},
Err(_) => Err(LoadFailed),
}
}
pub fn parse_save(src: &str) -> Result<Save, SaveErrors> {
let mut save = VecMap::new();
let mut errors = VecMap::new();
for src in src.split("@").skip(1) {
let maybe_num = src.chars()
.take_while(|c| c.is_numeric())
.collect::<String>()
.parse::<usize>()
.ok();
if let Some(num) = maybe_num {
let prog_src = src.chars()
.skip_while(|&c| c != '\n')
.skip(1)
.collect::<String>();
match parse_program(&prog_src) {
Ok(prog) => {
save.insert(num, prog);
},
Err(errs) => {
errors.insert(num, errs);
}
}
}
}
if errors.len() > 0 {
Err(errors)
} else {
Ok(save)
}
}
pub fn pretty_print_errors(save_errors: SaveErrors) {
for (node_num, ref errors) in save_errors.iter() {
for &(line_num, ref error) in errors.iter() {
println!("Node {}: Line {}: {}\n", node_num, line_num, error);
}
}
}
#[test]
fn test_parse_save() {
let save = parse_save("@1\nADD 1\n@2\nADD 1\n").unwrap();
assert_eq!(save.len(), 2);
}