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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
mod parser;
mod iterator;
use iterator::Iterator;
use std::io::{self, BufReader, prelude::*};
use std::fs::File;
use std::char;
#[derive(Debug)]
pub enum PropertyType {
Property,
Key,
Value,
Whitespace,
Comment,
LineBreak,
EscapedValue,
Separator,
}
#[derive(Debug)]
pub struct PropertyValue {
start: usize,
end: usize,
children: Option<Vec<PropertyValue>>,
type_: PropertyType,
}
pub struct Properties;
impl Properties {
pub fn new() -> Properties {
Properties {}
}
pub fn parse_file(file: &File) -> io::Result<()> {
let mut reader = BufReader::new(file);
let mut contents = String::new();
reader.read_to_string(&mut contents)?;
Self::parse(&contents);
Ok(())
}
pub fn parse(contents: &String) {
let mut entries = Vec::new();
let mut iter = Iterator::new(contents);
loop {
let chr = match iter.peek() {
Some(chr) => chr,
None => break,
};
if chr.is_whitespace() {
entries.push(parser::read_whitespace(&mut iter));
} else if parser::is_comment_indicator(chr) {
entries.push(parser::read_comment(&mut iter));
} else {
entries.push(parser::read_property(&mut iter));
}
}
Self::build_property(&entries, &iter);
}
fn build_property_component(value: &PropertyValue, iter: &Iterator) -> String {
let mut component = String::new();
let mut start = value.start;
if value.children.is_some() {
for child in value.children.as_ref().unwrap() {
component.push_str(&iter.get_range(start, child.start));
if let PropertyType::EscapedValue = child.type_ {
let chr = iter.get(child.start + 1).unwrap();
component.push(match chr {
't' => '\t',
'r' => '\r',
'n' => '\n',
'f' => '\x0c',
'u' => {
let num = u32::from_str_radix(&iter.get_range(
child.start + 2,
child.start + 6,
), 16).unwrap_or(0);
char::from_u32(num).unwrap()
},
_ => chr,
});
} else if let PropertyType::LineBreak = child.type_ {
}
start = child.end;
}
}
component.push_str(&iter.get_range(start, value.end));
component
}
fn build_property(values: &Vec<PropertyValue>, iter: &Iterator) {
for value in values {
if let PropertyType::Property = value.type_ {
let children = value.children.as_ref().unwrap();
let key = Self::build_property_component(&children[0], iter);
let value = Self::build_property_component(&children[2], iter);
println!("{}: {}", key, value);
}
}
}
}