Switched .get to Result instead of Option
Getty Ritter
7 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 | |