瀏覽代碼

Implement custom Error struct, remove error_chain

and fix some clippy warnings.
Johannes Hofmann 7 年之前
父節點
當前提交
325514eb98
共有 12 個文件被更改,包括 212 次插入96 次删除
  1. 0
    1
      Cargo.toml
  2. 1
    3
      examples/count.rs
  3. 21
    18
      src/blob.rs
  4. 13
    12
      src/block.rs
  5. 3
    3
      src/dense.rs
  6. 10
    10
      src/elements.rs
  7. 145
    0
      src/error.rs
  8. 0
    25
      src/errors.rs
  9. 2
    4
      src/lib.rs
  10. 11
    14
      src/mmap_blob.rs
  11. 1
    1
      src/reader.rs
  12. 5
    5
      src/util.rs

+ 0
- 1
Cargo.toml 查看文件

@@ -25,6 +25,5 @@ protobuf = "=1.6"
25 25
 byteorder = "1.1"
26 26
 flate2 = { version = "1.0", optional = true }
27 27
 inflate = "0.4"
28
-error-chain = "0.11"
29 28
 memmap = "0.6"
30 29
 rayon = "1.0"

+ 1
- 3
examples/count.rs 查看文件

@@ -1,11 +1,9 @@
1 1
 // Count the number of nodes, ways and relations in a PBF file given as the
2 2
 // first command line argument.
3 3
 
4
-extern crate error_chain;
5 4
 extern crate osmpbf;
6 5
 
7 6
 use osmpbf::*;
8
-use error_chain::ChainedError;
9 7
 
10 8
 fn main() {
11 9
     let arg = std::env::args_os().nth(1).expect("need a *.osm.pbf file as argument");
@@ -31,7 +29,7 @@ fn main() {
31 29
             println!("Relations: {}", relations);
32 30
         },
33 31
         Err(e) => {
34
-            println!("{}", e.display_chain().to_string());
32
+            println!("{}", e);
35 33
         },
36 34
     }
37 35
 }

+ 21
- 18
src/blob.rs 查看文件

@@ -5,7 +5,7 @@ extern crate byteorder;
5 5
 
6 6
 use block::{HeaderBlock, PrimitiveBlock};
7 7
 use byteorder::ReadBytesExt;
8
-use errors::*;
8
+use error::{BlobError, Result, new_blob_error, new_protobuf_error};
9 9
 use proto::fileformat;
10 10
 use std::fs::File;
11 11
 use std::io::{BufReader, Read};
@@ -64,8 +64,8 @@ pub struct Blob {
64 64
 impl Blob {
65 65
     fn new(header: fileformat::BlobHeader, blob: fileformat::Blob) -> Blob {
66 66
         Blob {
67
-            header: header,
68
-            blob: blob
67
+            header,
68
+            blob
69 69
         }
70 70
     }
71 71
 
@@ -100,7 +100,6 @@ impl Blob {
100 100
     pub fn to_headerblock(&self) -> Result<HeaderBlock> {
101 101
         decode_blob(&self.blob)
102 102
             .map(HeaderBlock::new)
103
-            .chain_err(|| "failed to decode blob to header block")
104 103
     }
105 104
 
106 105
     /// Tries to decode the blob to a `PrimitiveBlock`. This operation might involve an expensive
@@ -108,7 +107,6 @@ impl Blob {
108 107
     pub fn to_primitiveblock(&self) -> Result<PrimitiveBlock> {
109 108
         decode_blob(&self.blob)
110 109
             .map(PrimitiveBlock::new)
111
-            .chain_err(|| "failed to decode blob to primitive block")
112 110
     }
113 111
 }
114 112
 
@@ -137,7 +135,7 @@ impl<R: Read> BlobReader<R> {
137 135
     /// ```
138 136
     pub fn new(reader: R) -> BlobReader<R> {
139 137
         BlobReader {
140
-            reader: reader,
138
+            reader,
141 139
             last_blob_ok: true,
142 140
         }
143 141
     }
@@ -181,11 +179,12 @@ impl<R: Read> Iterator for BlobReader<R> {
181 179
             Err(e) => {
182 180
                 match e.kind() {
183 181
                     ::std::io::ErrorKind::UnexpectedEof => {
182
+                        //TODO This also accepts corrupted files in the case of 1-3 available bytes
184 183
                         return None
185 184
                     },
186 185
                     _ => {
187 186
                         self.last_blob_ok = false;
188
-                        return Some(Err(Error::with_chain(e, "Could not decode blob header size")));
187
+                        return Some(Err(new_blob_error(BlobError::InvalidHeaderSize)));
189 188
                     },
190 189
                 }
191 190
             },
@@ -193,14 +192,14 @@ impl<R: Read> Iterator for BlobReader<R> {
193 192
 
194 193
         if header_size >= MAX_BLOB_HEADER_SIZE {
195 194
             self.last_blob_ok = false;
196
-            return Some(Err(ErrorKind::BlobHeaderTooBig(header_size).into()));
195
+            return Some(Err(new_blob_error(BlobError::HeaderTooBig{size: header_size})));
197 196
         }
198 197
 
199 198
         let header: fileformat::BlobHeader = match parse_message_from_reader(&mut self.reader.by_ref().take(header_size)) {
200 199
             Ok(header) => header,
201 200
             Err(e) => {
202 201
                 self.last_blob_ok = false;
203
-                return Some(Err(Error::with_chain(e, "Could not decode BlobHeader")));
202
+                return Some(Err(new_protobuf_error(e, "blob header")));
204 203
             },
205 204
         };
206 205
 
@@ -208,7 +207,7 @@ impl<R: Read> Iterator for BlobReader<R> {
208 207
             Ok(blob) => blob,
209 208
             Err(e) => {
210 209
                 self.last_blob_ok = false;
211
-                return Some(Err(Error::with_chain(e, "Could not decode Blob")));
210
+                return Some(Err(new_protobuf_error(e, "blob content")));
212 211
             },
213 212
         };
214 213
 
@@ -222,16 +221,18 @@ pub(crate) fn decode_blob<T>(blob: &fileformat::Blob) -> Result<T>
222 221
     if blob.has_raw() {
223 222
         let size = blob.get_raw().len() as u64;
224 223
         if size < MAX_BLOB_MESSAGE_SIZE {
225
-            parse_message_from_bytes(blob.get_raw()).chain_err(|| "Could not parse raw data")
224
+            parse_message_from_bytes(blob.get_raw())
225
+                .map_err(|e| new_protobuf_error(e, "raw blob data"))
226 226
         } else {
227
-            Err(ErrorKind::BlobMessageTooBig(size).into())
227
+            Err(new_blob_error(BlobError::MessageTooBig{size}))
228 228
         }
229 229
     } else if blob.has_zlib_data() {
230 230
         let mut decoder = ZlibDecoder::new(blob.get_zlib_data())
231 231
             .take(MAX_BLOB_MESSAGE_SIZE);
232
-        parse_message_from_reader(&mut decoder).chain_err(|| "Could not parse zlib data")
232
+        parse_message_from_reader(&mut decoder)
233
+            .map_err(|e| new_protobuf_error(e, "blob zlib data"))
233 234
     } else {
234
-        bail!("Blob is missing fields 'raw' and 'zlib_data")
235
+        Err(new_blob_error(BlobError::Empty))
235 236
     }
236 237
 }
237 238
 
@@ -241,15 +242,17 @@ pub(crate) fn decode_blob<T>(blob: &fileformat::Blob) -> Result<T>
241 242
     if blob.has_raw() {
242 243
         let size = blob.get_raw().len() as u64;
243 244
         if size < MAX_BLOB_MESSAGE_SIZE {
244
-            parse_message_from_bytes(blob.get_raw()).chain_err(|| "Could not parse raw data")
245
+            parse_message_from_bytes(blob.get_raw())
246
+                .map_err(|e| new_protobuf_error(e, "raw blob data"))
245 247
         } else {
246
-            Err(ErrorKind::BlobMessageTooBig(size).into())
248
+            Err(new_blob_error(BlobError::MessageTooBig{size}))
247 249
         }
248 250
     } else if blob.has_zlib_data() {
249 251
         let mut decoder = DeflateDecoder::from_zlib(blob.get_zlib_data())
250 252
             .take(MAX_BLOB_MESSAGE_SIZE);
251
-        parse_message_from_reader(&mut decoder).chain_err(|| "Could not parse zlib data")
253
+        parse_message_from_reader(&mut decoder)
254
+            .map_err(|e| new_protobuf_error(e, "blob zlib data"))
252 255
     } else {
253
-        bail!("Blob is missing fields 'raw' and 'zlib_data")
256
+        Err(new_blob_error(BlobError::Empty))
254 257
     }
255 258
 }

+ 13
- 12
src/block.rs 查看文件

@@ -2,7 +2,7 @@
2 2
 
3 3
 use dense::DenseNodeIter;
4 4
 use elements::{Element, Node, Way, Relation};
5
-use errors::*;
5
+use error::{ErrorKind, Result, new_error};
6 6
 use proto::osmformat;
7 7
 use std;
8 8
 
@@ -15,7 +15,7 @@ pub struct HeaderBlock {
15 15
 
16 16
 impl HeaderBlock {
17 17
     pub(crate) fn new(header: osmformat::HeaderBlock) -> HeaderBlock {
18
-        HeaderBlock { header: header }
18
+        HeaderBlock { header }
19 19
     }
20 20
 
21 21
     /// Returns a list of required features that a parser needs to implement to parse the following
@@ -38,7 +38,7 @@ pub struct PrimitiveBlock {
38 38
 
39 39
 impl PrimitiveBlock {
40 40
     pub(crate) fn new(block: osmformat::PrimitiveBlock) -> PrimitiveBlock {
41
-        PrimitiveBlock { block: block }
41
+        PrimitiveBlock { block }
42 42
     }
43 43
 
44 44
     /// Returns an iterator over the elements in this `PrimitiveBlock`.
@@ -92,8 +92,8 @@ impl<'a> PrimitiveGroup<'a> {
92 92
            group: &'a osmformat::PrimitiveGroup)
93 93
           -> PrimitiveGroup<'a> {
94 94
         PrimitiveGroup {
95
-            block: block,
96
-            group: group,
95
+            block,
96
+            group,
97 97
         }
98 98
     }
99 99
 
@@ -142,7 +142,7 @@ enum ElementsIterState {
142 142
 impl<'a> BlockElementsIter<'a> {
143 143
     fn new(block: &'a osmformat::PrimitiveBlock) -> BlockElementsIter<'a> {
144 144
         BlockElementsIter {
145
-            block: block,
145
+            block,
146 146
             state: ElementsIterState::Group,
147 147
             groups: block.get_primitivegroup().iter(),
148 148
             dense_nodes: DenseNodeIter::empty(block),
@@ -240,7 +240,7 @@ pub struct GroupIter<'a> {
240 240
 impl<'a> GroupIter<'a> {
241 241
     fn new(block: &'a osmformat::PrimitiveBlock) -> GroupIter<'a> {
242 242
         GroupIter {
243
-            block: block,
243
+            block,
244 244
             groups: block.get_primitivegroup().iter(),
245 245
         }
246 246
     }
@@ -275,7 +275,7 @@ impl<'a> GroupNodeIter<'a> {
275 275
            group: &'a osmformat::PrimitiveGroup)
276 276
           -> GroupNodeIter<'a> {
277 277
         GroupNodeIter {
278
-            block: block,
278
+            block,
279 279
             nodes: group.get_nodes().iter(),
280 280
         }
281 281
     }
@@ -310,7 +310,7 @@ impl<'a> GroupWayIter<'a> {
310 310
            group: &'a osmformat::PrimitiveGroup)
311 311
           -> GroupWayIter<'a> {
312 312
         GroupWayIter {
313
-            block: block,
313
+            block,
314 314
             ways: group.get_ways().iter(),
315 315
         }
316 316
     }
@@ -345,7 +345,7 @@ impl<'a> GroupRelationIter<'a> {
345 345
            group: &'a osmformat::PrimitiveGroup)
346 346
           -> GroupRelationIter<'a> {
347 347
         GroupRelationIter {
348
-            block: block,
348
+            block,
349 349
             rels: group.get_relations().iter(),
350 350
         }
351 351
     }
@@ -370,9 +370,10 @@ impl<'a> ExactSizeIterator for GroupRelationIter<'a> {}
370 370
 
371 371
 pub(crate) fn str_from_stringtable(block: &osmformat::PrimitiveBlock, index: usize) -> Result<&str> {
372 372
     if let Some(vec) = block.get_stringtable().get_s().get(index) {
373
+        //TODO at location to ErrorKind::Utf8
373 374
         std::str::from_utf8(vec)
374
-            .chain_err(|| "failed to decode string from string table")
375
+            .map_err(|e| new_error(ErrorKind::Utf8(e)))
375 376
     } else {
376
-        Err(ErrorKind::StringtableIndexOutOfBounds(index).into())
377
+        Err(new_error(ErrorKind::StringtableIndexOutOfBounds{index}))
377 378
     }
378 379
 }

+ 3
- 3
src/dense.rs 查看文件

@@ -1,6 +1,6 @@
1 1
 //! Iterate over the dense nodes in a `PrimitiveGroup`
2 2
 
3
-use errors::*;
3
+use error::Result;
4 4
 use proto::osmformat;
5 5
 use block::str_from_stringtable;
6 6
 use std;
@@ -90,7 +90,7 @@ impl<'a> DenseNodeIter<'a> {
90 90
            osmdense: &'a osmformat::DenseNodes) -> DenseNodeIter<'a> {
91 91
         let info = osmdense.get_denseinfo();
92 92
         DenseNodeIter {
93
-            block: block,
93
+            block,
94 94
             dids: osmdense.get_id().iter(),
95 95
             cid: 0,
96 96
             versions: info.get_version().iter(),
@@ -113,7 +113,7 @@ impl<'a> DenseNodeIter<'a> {
113 113
 
114 114
     pub(crate) fn empty(block: &'a osmformat::PrimitiveBlock) -> DenseNodeIter<'a> {
115 115
         DenseNodeIter {
116
-            block: block,
116
+            block,
117 117
             dids: [].iter(),
118 118
             cid: 0,
119 119
             versions: [].iter(),

+ 10
- 10
src/elements.rs 查看文件

@@ -1,6 +1,6 @@
1 1
 //! Nodes, ways and relations
2 2
 
3
-use errors::*;
3
+use error::Result;
4 4
 use block::str_from_stringtable;
5 5
 use dense::DenseNode;
6 6
 use proto::osmformat::PrimitiveBlock;
@@ -36,8 +36,8 @@ pub struct Node<'a> {
36 36
 impl<'a> Node<'a> {
37 37
     pub(crate) fn new(block: &'a PrimitiveBlock, osmnode: &'a osmformat::Node) -> Node<'a> {
38 38
         Node {
39
-            block: block,
40
-            osmnode: osmnode,
39
+            block,
40
+            osmnode,
41 41
         }
42 42
     }
43 43
 
@@ -130,8 +130,8 @@ pub struct Way<'a> {
130 130
 impl<'a> Way<'a> {
131 131
     pub(crate) fn new(block: &'a PrimitiveBlock, osmway: &'a osmformat::Way) -> Way<'a> {
132 132
         Way {
133
-            block: block,
134
-            osmway: osmway,
133
+            block,
134
+            osmway,
135 135
         }
136 136
     }
137 137
 
@@ -222,8 +222,8 @@ pub struct Relation<'a> {
222 222
 impl<'a> Relation<'a> {
223 223
     pub(crate) fn new(block: &'a PrimitiveBlock, osmrel: &'a osmformat::Relation) -> Relation<'a> {
224 224
         Relation {
225
-            block: block,
226
-            osmrel: osmrel,
225
+            block,
226
+            osmrel,
227 227
         }
228 228
     }
229 229
 
@@ -372,7 +372,7 @@ pub struct RelMemberIter<'a> {
372 372
 impl<'a> RelMemberIter<'a> {
373 373
     fn new(block: &'a PrimitiveBlock, osmrel: &'a osmformat::Relation) -> RelMemberIter<'a> {
374 374
         RelMemberIter {
375
-            block: block,
375
+            block,
376 376
             role_sids: osmrel.get_roles_sid().iter(),
377 377
             member_id_deltas: osmrel.get_memids().iter(),
378 378
             member_types: osmrel.get_types().iter(),
@@ -479,8 +479,8 @@ pub struct Info<'a> {
479 479
 impl<'a> Info<'a> {
480 480
     fn new(block: &'a PrimitiveBlock, info: &'a osmformat::Info) -> Info<'a> {
481 481
         Info {
482
-            block: block,
483
-            info: info,
482
+            block,
483
+            info,
484 484
         }
485 485
     }
486 486
 

+ 145
- 0
src/error.rs 查看文件

@@ -0,0 +1,145 @@
1
+use std::error::Error as StdError;
2
+use std::fmt;
3
+use std::io;
4
+use std::result;
5
+use std::str;
6
+use std::str::Utf8Error;
7
+
8
+use protobuf::ProtobufError;
9
+
10
+// Error data structures are modeled just like in the `csv` crate by BurntSushi.
11
+
12
+pub(crate) fn new_error(kind: ErrorKind) -> Error {
13
+    Error(Box::new(kind))
14
+}
15
+
16
+pub(crate) fn new_blob_error(kind: BlobError) -> Error {
17
+    Error(Box::new(ErrorKind::Blob(kind)))
18
+}
19
+
20
+pub(crate) fn new_protobuf_error(err: ProtobufError, location: &'static str) -> Error {
21
+    Error(Box::new(ErrorKind::Protobuf{ err, location }))
22
+}
23
+
24
+/// A type alias for `Result<T, osmpbf::Error>`.
25
+pub type Result<T> = result::Result<T, Error>;
26
+
27
+/// An error that can occur when reading PBF files.
28
+#[derive(Debug)]
29
+pub struct Error(Box<ErrorKind>);
30
+
31
+impl Error {
32
+    /// Return the specific type of this error.
33
+    pub fn kind(&self) -> &ErrorKind {
34
+        &self.0
35
+    }
36
+
37
+    /// Unwrap this error into its underlying type.
38
+    pub fn into_kind(self) -> ErrorKind {
39
+        *self.0
40
+    }
41
+}
42
+
43
+/// The specific type of an error.
44
+#[derive(Debug)]
45
+pub enum ErrorKind {
46
+    Io(io::Error),
47
+    Protobuf{err: ProtobufError, location: &'static str},
48
+    Utf8(Utf8Error),
49
+    StringtableIndexOutOfBounds{index: usize},
50
+    Blob(BlobError),
51
+
52
+    //TODO add UnexpectedPrimitiveBlock
53
+
54
+    /// Hints that destructuring should not be exhaustive.
55
+    ///
56
+    /// This enum may grow additional variants, so this makes sure clients
57
+    /// don't count on exhaustive matching. (Otherwise, adding a new variant
58
+    /// could break existing code.)
59
+    #[doc(hidden)]
60
+    __Nonexhaustive,
61
+}
62
+
63
+/// An error that occurs when decoding a blob.
64
+#[derive(Debug)]
65
+pub enum BlobError {
66
+    InvalidHeaderSize,
67
+    HeaderTooBig{size: u64},
68
+    MessageTooBig{size: u64},
69
+    Empty,
70
+    /// Hints that destructuring should not be exhaustive.
71
+    #[doc(hidden)]
72
+    __Nonexhaustive,
73
+}
74
+
75
+
76
+impl From<io::Error> for Error {
77
+    fn from(err: io::Error) -> Error {
78
+        new_error(ErrorKind::Io(err))
79
+    }
80
+}
81
+
82
+impl From<Error> for io::Error {
83
+    fn from(err: Error) -> io::Error {
84
+        io::Error::new(io::ErrorKind::Other, err)
85
+    }
86
+}
87
+
88
+impl StdError for Error {
89
+    fn description(&self) -> &str {
90
+        match *self.0 {
91
+            ErrorKind::Io(ref err) => err.description(),
92
+            ErrorKind::Protobuf{ref err, ..} => err.description(),
93
+            ErrorKind::Utf8(ref err) => err.description(),
94
+            ErrorKind::StringtableIndexOutOfBounds{..} => "stringtable index out of bounds",
95
+            ErrorKind::Blob(BlobError::InvalidHeaderSize) => "blob header size could not be decoded",
96
+            ErrorKind::Blob(BlobError::HeaderTooBig{..}) => "blob header is too big",
97
+            ErrorKind::Blob(BlobError::MessageTooBig{..}) => "blob message is too big",
98
+            ErrorKind::Blob(BlobError::Empty) => "blob is missing fields 'raw' and 'zlib_data",
99
+            _ => unreachable!(),
100
+        }
101
+    }
102
+
103
+    fn cause(&self) -> Option<&StdError> {
104
+        match *self.0 {
105
+            ErrorKind::Io(ref err) => Some(err),
106
+            ErrorKind::Protobuf{ref err, ..} => Some(err),
107
+            ErrorKind::Utf8(ref err) => Some(err),
108
+            ErrorKind::StringtableIndexOutOfBounds{..} => None,
109
+            ErrorKind::Blob(BlobError::InvalidHeaderSize) => None,
110
+            ErrorKind::Blob(BlobError::HeaderTooBig{..}) => None,
111
+            ErrorKind::Blob(BlobError::MessageTooBig{..}) => None,
112
+            ErrorKind::Blob(BlobError::Empty) => None,
113
+            _ => unreachable!(),
114
+        }
115
+    }
116
+}
117
+
118
+impl fmt::Display for Error {
119
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
120
+        match *self.0 {
121
+            ErrorKind::Io(ref err) => err.fmt(f),
122
+            ErrorKind::Protobuf{ref err, location} => {
123
+                write!(f, "protobuf error at '{}': {}", location, err)
124
+            },
125
+            ErrorKind::Utf8(ref err) => err.fmt(f),
126
+            ErrorKind::StringtableIndexOutOfBounds { index } => {
127
+                write!(f, "stringtable index out of bounds: {}", index)
128
+            },
129
+            ErrorKind::Blob(BlobError::InvalidHeaderSize) => {
130
+                write!(f, "blob header size could not be decoded")
131
+            },
132
+            ErrorKind::Blob(BlobError::HeaderTooBig { size }) => {
133
+                write!(f, "blob header is too big: {} bytes", size)
134
+            },
135
+            ErrorKind::Blob(BlobError::MessageTooBig { size }) => {
136
+                write!(f, "blob message is too big: {} bytes", size)
137
+            },
138
+            ErrorKind::Blob(BlobError::Empty) => {
139
+                write!(f, "blob is missing fields 'raw' and 'zlib_data'")
140
+            },
141
+            _ => unreachable!(),
142
+        }
143
+    }
144
+}
145
+

+ 0
- 25
src/errors.rs 查看文件

@@ -1,25 +0,0 @@
1
-error_chain!{
2
-    foreign_links {
3
-        Io(::std::io::Error);
4
-        Protobuf(::protobuf::ProtobufError);
5
-    }
6
-
7
-    errors {
8
-        StringtableIndexOutOfBounds(index: usize) {
9
-            description("stringtable index out of bounds")
10
-            display("stringtable index out of bounds: {}", index)
11
-        }
12
-
13
-        BlobHeaderTooBig(size: u64) {
14
-            description("blob header is too big")
15
-            display("blob header is too big: {} bytes", size)
16
-        }
17
-
18
-        BlobMessageTooBig(size: u64) {
19
-            description("blob message is too big")
20
-            display("blob message is too big: {} bytes", size)
21
-        }
22
-
23
-        //TODO add UnexpectedPrimitiveBlock
24
-    }
25
-}

+ 2
- 4
src/lib.rs 查看文件

@@ -75,8 +75,6 @@ extern crate byteorder;
75 75
 extern crate memmap;
76 76
 extern crate protobuf;
77 77
 extern crate rayon;
78
-#[macro_use]
79
-extern crate error_chain;
80 78
 
81 79
 #[cfg(feature = "system-libz")]
82 80
 extern crate flate2;
@@ -89,11 +87,11 @@ pub use blob::*;
89 87
 pub use block::*;
90 88
 pub use dense::*;
91 89
 pub use elements::*;
92
-pub use errors::{Error, ErrorKind, Result, ResultExt};
90
+pub use error::{Error, ErrorKind, Result};
93 91
 pub use mmap_blob::*;
94 92
 pub use reader::*;
95 93
 
96
-mod errors;
94
+mod error;
97 95
 mod proto;
98 96
 pub mod reader;
99 97
 pub mod blob;

+ 11
- 14
src/mmap_blob.rs 查看文件

@@ -7,7 +7,7 @@ extern crate memmap;
7 7
 use blob::{BlobDecode, BlobType, decode_blob};
8 8
 use block::{HeaderBlock, PrimitiveBlock};
9 9
 use byteorder::ByteOrder;
10
-use errors::*;
10
+use error::{BlobError, Result, new_blob_error, new_protobuf_error};
11 11
 use proto::{fileformat, osmformat};
12 12
 use self::fileformat::BlobHeader;
13 13
 use std::fs::File;
@@ -42,7 +42,7 @@ impl Mmap {
42 42
     pub unsafe fn from_file(file: &File) -> Result<Mmap> {
43 43
         memmap::Mmap::map(file)
44 44
             .map(|m| Mmap { mmap: m })
45
-            .chain_err(|| "Could not create memory map from file")
45
+            .map_err(|e| e.into())
46 46
     }
47 47
 
48 48
     /// Creates a memory map from a given path.
@@ -65,7 +65,7 @@ impl Mmap {
65 65
         let file = File::open(&path)?;
66 66
         memmap::Mmap::map(&file)
67 67
             .map(|m| Mmap { mmap: m })
68
-            .chain_err(|| format!("Could not create memory map from path {}", path.as_ref().display()))
68
+            .map_err(|e| e.into())
69 69
     }
70 70
 
71 71
     /// Returns an iterator over the blobs in this memory map.
@@ -90,7 +90,7 @@ impl<'a> MmapBlob<'a> {
90 90
     /// `PrimitiveBlock`). This operation might involve an expensive decompression step.
91 91
     pub fn decode(&'a self) -> Result<BlobDecode<'a>> {
92 92
         let blob: fileformat::Blob = parse_message_from_bytes(self.data)
93
-            .chain_err(|| "failed to parse Blob")?;
93
+            .map_err(|e| new_protobuf_error(e, "blob content"))?;
94 94
         match self.header.get_field_type() {
95 95
             "OSMHeader" => {
96 96
                 let block = Box::new(HeaderBlock::new(decode_blob(&blob)?));
@@ -139,7 +139,7 @@ impl<'a> MmapBlobReader<'a> {
139 139
     /// ```
140 140
     pub fn new(mmap: &Mmap) -> MmapBlobReader {
141 141
         MmapBlobReader {
142
-            mmap: mmap,
142
+            mmap,
143 143
             offset: 0,
144 144
             last_blob_ok: true,
145 145
         }
@@ -156,10 +156,7 @@ impl<'a> Iterator for MmapBlobReader<'a> {
156 156
             0 => return None,
157 157
             1 ... 3 => {
158 158
                 self.last_blob_ok = false;
159
-                let io_error = ::std::io::Error::new(
160
-                    ::std::io::ErrorKind::UnexpectedEof, "failed to parse blob header length"
161
-                );
162
-                return Some(Err(Error::from_kind(ErrorKind::Io(io_error))));
159
+                return Some(Err(new_blob_error(BlobError::InvalidHeaderSize)));
163 160
             },
164 161
             _ => {},
165 162
         }
@@ -168,7 +165,7 @@ impl<'a> Iterator for MmapBlobReader<'a> {
168 165
 
169 166
         if header_size as u64 >= ::blob::MAX_BLOB_HEADER_SIZE {
170 167
             self.last_blob_ok = false;
171
-            return Some(Err(ErrorKind::BlobHeaderTooBig(header_size as u64).into()));
168
+            return Some(Err(new_blob_error(BlobError::HeaderTooBig{size: header_size as u64})));
172 169
         }
173 170
 
174 171
         if slice.len() < 4 + header_size {
@@ -176,14 +173,14 @@ impl<'a> Iterator for MmapBlobReader<'a> {
176 173
             let io_error = ::std::io::Error::new(
177 174
                 ::std::io::ErrorKind::UnexpectedEof, "content too short for header"
178 175
             );
179
-            return Some(Err(Error::from_kind(ErrorKind::Io(io_error))));
176
+            return Some(Err(io_error.into()));
180 177
         }
181 178
 
182 179
         let header: BlobHeader = match parse_message_from_bytes(&slice[4..(4 + header_size)]) {
183 180
             Ok(x) => x,
184 181
             Err(e) => {
185 182
                 self.last_blob_ok = false;
186
-                return Some(Err(e));
183
+                return Some(Err(new_protobuf_error(e, "blob header")));
187 184
             },
188 185
         };
189 186
 
@@ -195,13 +192,13 @@ impl<'a> Iterator for MmapBlobReader<'a> {
195 192
             let io_error = ::std::io::Error::new(
196 193
                 ::std::io::ErrorKind::UnexpectedEof, "content too short for block data"
197 194
             );
198
-            return Some(Err(Error::from_kind(ErrorKind::Io(io_error))));
195
+            return Some(Err(io_error.into()));
199 196
         }
200 197
 
201 198
         self.offset += chunk_size;
202 199
 
203 200
         Some(Ok(MmapBlob {
204
-            header: header,
201
+            header,
205 202
             data: &slice[(4 + header_size)..chunk_size]
206 203
         }))
207 204
     }

+ 1
- 1
src/reader.rs 查看文件

@@ -2,7 +2,7 @@
2 2
 
3 3
 use blob::{BlobDecode, BlobReader};
4 4
 use elements::Element;
5
-use errors::*;
5
+use error::Result;
6 6
 use rayon::prelude::*;
7 7
 use std::fs::File;
8 8
 use std::io::{BufReader, Read};

+ 5
- 5
src/util.rs 查看文件

@@ -1,8 +1,8 @@
1
-use errors::*;
1
+use protobuf::ProtobufError;
2 2
 use std::io::Read;
3 3
 
4 4
 
5
-pub(crate) fn parse_message_from_bytes<M>(bytes: &[u8]) -> Result<M>
5
+pub(crate) fn parse_message_from_bytes<M>(bytes: &[u8]) -> Result<M, ProtobufError>
6 6
     where M: ::protobuf::Message
7 7
 {
8 8
     let mut stream = ::protobuf::CodedInputStream::from_bytes(bytes);
@@ -12,11 +12,11 @@ pub(crate) fn parse_message_from_bytes<M>(bytes: &[u8]) -> Result<M>
12 12
     if message.is_initialized() {
13 13
         Ok(message)
14 14
     } else {
15
-        Err(::protobuf::ProtobufError::message_not_initialized("").into())
15
+        Err(::protobuf::ProtobufError::message_not_initialized(""))
16 16
     }
17 17
 }
18 18
 
19
-pub(crate) fn parse_message_from_reader<R, M>(reader: &mut R) -> Result<M>
19
+pub(crate) fn parse_message_from_reader<R, M>(reader: &mut R) -> Result<M, ProtobufError>
20 20
     where R: Read,
21 21
           M: ::protobuf::Message,
22 22
 {
@@ -29,6 +29,6 @@ pub(crate) fn parse_message_from_reader<R, M>(reader: &mut R) -> Result<M>
29 29
     if message.is_initialized() {
30 30
         Ok(message)
31 31
     } else {
32
-        Err(::protobuf::ProtobufError::message_not_initialized("").into())
32
+        Err(::protobuf::ProtobufError::message_not_initialized(""))
33 33
     }
34 34
 }