1use std::error;
2use std::fmt::{Debug, Display, Formatter};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub enum ErrorKind {
6 Io,
7 Syntax,
8 Version,
9 Shape,
10 Unsupported,
11 Model,
12}
13
14pub enum Error {
15 Io(std::io::Error),
16 Syntax(String),
17 CityJSON(cityjson::error::Error),
18 MissingVersion,
19 ExpectedCityJSON(String),
20 ExpectedCityJSONFeature(String),
21 UnsupportedType(String),
22 UnsupportedVersion { found: String, supported: String },
23 Streaming(String),
24 Import(String),
25 UnsupportedFeature(String),
26}
27
28pub type Result<T> = std::result::Result<T, Error>;
29
30impl Error {
31 pub fn kind(&self) -> ErrorKind {
32 match self {
33 Self::Io(_) => ErrorKind::Io,
34 Self::Syntax(_) => ErrorKind::Syntax,
35 Self::CityJSON(_) => ErrorKind::Model,
36 Self::MissingVersion => ErrorKind::Version,
37 Self::ExpectedCityJSON(_) | Self::ExpectedCityJSONFeature(_) => ErrorKind::Shape,
38 Self::UnsupportedType(_)
39 | Self::UnsupportedVersion { .. }
40 | Self::UnsupportedFeature(_) => ErrorKind::Unsupported,
41 Self::Streaming(_) => ErrorKind::Shape,
42 Self::Import(_) => ErrorKind::Model,
43 }
44 }
45}
46
47impl Display for Error {
48 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
49 match self {
50 Self::Io(error) => write!(f, "I/O error: {error}"),
51 Self::Syntax(error) => write!(f, "JSON error: {error}"),
52 Self::CityJSON(error) => write!(f, "cityjson error: {error}"),
53 Self::MissingVersion => write!(f, "CityJSON object must contain a version member"),
54 Self::ExpectedCityJSON(found) => {
55 write!(f, "expected a CityJSON object, found {found}")
56 }
57 Self::ExpectedCityJSONFeature(found) => {
58 write!(f, "expected a CityJSONFeature object, found {found}")
59 }
60 Self::UnsupportedType(found) => {
61 write!(f, "unsupported CityJSON type: {found}")
62 }
63 Self::UnsupportedVersion { found, supported } => {
64 write!(
65 f,
66 "unsupported CityJSON version {found}; supported versions: {supported}"
67 )
68 }
69 Self::Streaming(message) => write!(f, "streaming error: {message}"),
70 Self::Import(message) => write!(f, "import error: {message}"),
71 Self::UnsupportedFeature(message) => write!(f, "unsupported feature: {message}"),
72 }
73 }
74}
75
76impl Debug for Error {
77 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
78 Display::fmt(self, f)
79 }
80}
81
82impl error::Error for Error {}
83
84impl From<std::io::Error> for Error {
85 fn from(value: std::io::Error) -> Self {
86 Self::Io(value)
87 }
88}
89
90impl From<cityjson::error::Error> for Error {
91 fn from(value: cityjson::error::Error) -> Self {
92 Self::CityJSON(value)
93 }
94}
95
96#[cfg(feature = "json")]
97impl From<cityjson_json::Error> for Error {
98 fn from(value: cityjson_json::Error) -> Self {
99 match value {
100 cityjson_json::Error::Json(error) => Self::Syntax(error.to_string()),
101 cityjson_json::Error::Utf8(error) => Self::Syntax(error.to_string()),
102 cityjson_json::Error::CityJson(error) => Self::CityJSON(error),
103 cityjson_json::Error::UnsupportedType(found) => Self::UnsupportedType(found),
104 cityjson_json::Error::UnsupportedVersion(found) => Self::UnsupportedVersion {
105 found,
106 supported: cityjson::CityJSONVersion::V2_0.to_string(),
107 },
108 cityjson_json::Error::MalformedRootObject(reason) => Self::Syntax(reason.to_owned()),
109 cityjson_json::Error::InvalidValue(reason) => Self::Import(reason),
110 cityjson_json::Error::UnsupportedFeature(feature) => {
111 Self::UnsupportedFeature(feature.to_owned())
112 }
113 cityjson_json::Error::UnresolvedCityObjectReference {
114 source_id,
115 target_id,
116 relation,
117 } => Self::Import(format!(
118 "unresolved CityObject {relation} reference from '{source_id}' to '{target_id}'"
119 )),
120 }
121 }
122}