Switched .get to Result instead of Option
Getty Ritter
6 years ago
10 | 10 | } |
11 | 11 | |
12 | 12 | |
13 | /// A `Record` is a single bundle of key-value pairs with a few pieces | |
14 | /// of optional metadata. This preserves the order of the values | |
15 | /// contained. | |
13 | 16 | #[derive(Eq, PartialEq, Debug)] |
14 | 17 | pub struct Record { |
15 | 18 | pub rec_type: Option<String>, |
17 | 20 | } |
18 | 21 | |
19 | 22 | impl Record { |
23 | /// Write the serialized version of this `Record` to the provided `Write`r | |
20 | 24 | pub fn write<W>(&self, w: &mut W) -> std::io::Result<()> |
21 | 25 | where W: std::io::Write |
22 | 26 | { |
27 | 31 | write!(w, "\n") |
28 | 32 | } |
29 | 33 | |
34 | /// Turn this `Record` into a serialized string representation | |
35 | pub fn to_string(&self) -> std::io::Result<String> { | |
36 | let mut s = std::io::Cursor::new(Vec::new()); | |
37 | self.write(&mut s)?; | |
38 | // XXX: this SHOULD be fine, but make sure! | |
39 | Ok(String::from_utf8(s.into_inner()).unwrap()) | |
40 | } | |
41 | ||
42 | /// Return the number of fields in this record | |
30 | 43 | pub fn size(&self) -> usize { |
31 | 44 | self.fields.len() |
32 | 45 | } |
33 | 46 | |
34 |
|
|
47 | /// Return the value of the field named by the argument if it | |
48 | /// exists | |
49 | pub fn get<'a>(&'a self, name: &str) -> Result<&'a str, RecError> { | |
35 | 50 | self.fields.iter() |
36 | 51 | .find(|&&(ref p, _)| p == name) |
37 | 52 | .map(|&(_, ref q)| q.as_ref()) |
38 | } | |
39 | } | |
40 | ||
41 | ||
53 | .ok_or(RecError::MissingField { name: name.to_owned() }) | |
54 | } | |
55 | } | |
56 | ||
57 | ||
58 | /// A `Recfile` is a sequence of `Record`. | |
42 | 59 | #[derive(Eq, PartialEq, Debug)] |
43 | 60 | pub struct Recfile { |
44 | 61 | pub records: Vec<Record>, |
45 | 62 | } |
46 | 63 | |
47 | 64 | impl Recfile { |
65 | /// Serialize this `Recfile` to the provided `Write`r | |
48 | 66 | pub fn write<W>(&self, w: &mut W) -> std::io::Result<()> |
49 | 67 | where W: std::io::Write |
50 | 68 | { |
55 | 73 | Ok(()) |
56 | 74 | } |
57 | 75 | |
76 | /// Turn this `Recfile` into a serialized string representation | |
77 | pub fn to_string(&self) -> std::io::Result<String> { | |
78 | let mut s = std::io::Cursor::new(Vec::new()); | |
79 | self.write(&mut s)?; | |
80 | // XXX: this SHOULD be fine, but make sure! | |
81 | Ok(String::from_utf8(s.into_inner()).unwrap()) | |
82 | } | |
83 | ||
84 | /// Modify this Recfile in-place by only keeping the records of a | |
85 | /// particular type | |
58 | 86 | pub fn filter_by_type(&mut self, type_name: &str) { |
59 | 87 | self.records.retain(|r| match r.rec_type { |
60 | 88 | Some(ref t) => t == type_name, |
62 | 90 | }); |
63 | 91 | } |
64 | 92 | |
93 | /// Iterate over a subset of the records in this recfile | |
65 | 94 | pub fn iter_by_type<'a>(&'a self, type_name: &'a str) -> RecIterator<'a> { |
66 | 95 | RecIterator { |
67 | 96 | typ: type_name, |
69 | 98 | } |
70 | 99 | } |
71 | 100 | |
101 | /// Iterate over _all_ the records in this recfile | |
72 | 102 | pub fn iter<'a>(&'a self) -> std::slice::Iter<'a, Record> { |
73 | 103 | self.records.iter() |
74 | 104 | } |
75 | 105 | } |
76 | 106 | |
77 | 107 | pub struct RecIterator<'a> { |
78 | pub typ: &'a str, | |
79 | pub rec: std::slice::Iter<'a, Record>, | |
108 | typ: &'a str, | |
109 | rec: std::slice::Iter<'a, Record>, | |
80 | 110 | } |
81 | 111 | |
82 | 112 | impl<'a> Iterator for RecIterator<'a> { |
108 | 138 | #[fail(display = "Invalid line: {}", ln)] |
109 | 139 | InvalidLine { |
110 | 140 | ln: String, |
141 | }, | |
142 | ||
143 | #[fail(display = "Missing key: {}", name)] | |
144 | MissingField { | |
145 | name: String, | |
111 | 146 | }, |
112 | 147 | } |
113 | 148 |