A Rust library for reading the OpenStreetMap PBF file format (*.osm.pbf).

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