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
use std::path::Path;
use std::io::{Result, Error, ErrorKind};
pub type Ltsv = Vec<Record>;
pub type Record = std::collections::HashMap<String, String>;
pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Vec<Record>> {
use std::fs::File;
use std::io::{BufReader, Read};
use std::iter::FromIterator;
let file = File::open(path)?;
let mut reader = BufReader::new(file);
let mut buf = String::new();
let _ = reader.read_to_string(&mut buf)?;
let content = buf.trim();
if content.is_empty() {
return Ok(vec![]);
}
let mut error = None;
let data = buf.trim().split("\n").map(|line|{
let _line = line.clone();
let iter = line.split("\t").map(|f|{
let _f = f.clone();
let split: Vec<&str> = f.splitn(2, ':').collect();
if error.is_none() && split.len() == 1 {
error = Some(Error::new(
ErrorKind::Other,
format!("Incorrect file format. Found line: `{}`. Found error field: `{}`", _line, _f)
));
(String::new(), String::new())
} else {
(split[0].to_owned(), split[1].to_owned())
}
});
Record::from_iter(iter)
}).collect();
if let Some(error) = error {
Err(error)
} else {
Ok(data)
}
}
pub fn save<P: AsRef<Path>>(data: Ltsv, path: P) -> Result<()> {
use std::fs::File;
use std::io::{BufWriter, Write};
let records: Vec<String> = data.iter().map(|record|{
let vec: Vec<String> = record.iter().map(|(k,v)|format!("{}:{}",k,v)).collect();
vec.join("\t")
}).collect();
let data = records.join("\n");
let file = File::create(path)?;
let mut writer = BufWriter::new(file);
writer.write_all(&data.into_bytes())?;
Ok(())
}