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(any(feature = "arrow", feature = "parquet"))]
97impl From<cityjson_arrow::error::Error> for Error {
98 fn from(value: cityjson_arrow::error::Error) -> Self {
99 match value {
100 cityjson_arrow::error::Error::Arrow(error) => Self::Import(error.to_string()),
101 cityjson_arrow::error::Error::Parquet(error) => Self::Import(error.to_string()),
102 cityjson_arrow::error::Error::CityJSON(error) => Self::CityJSON(error),
103 cityjson_arrow::error::Error::Json(error) => Self::Syntax(error.to_string()),
104 cityjson_arrow::error::Error::Conversion(message) => Self::Import(message),
105 cityjson_arrow::error::Error::Unsupported(message) => Self::UnsupportedFeature(message),
106 cityjson_arrow::error::Error::SchemaMismatch { expected, found } => Self::Import(
107 format!("expected Arrow schema: {expected}, found schema: {found}"),
108 ),
109 cityjson_arrow::error::Error::MissingField(field) => {
110 Self::Import(format!("missing Arrow field: {field}"))
111 }
112 cityjson_arrow::error::Error::Io(error) => Self::Io(error),
113 }
114 }
115}
116
117#[cfg(feature = "json")]
118impl From<cityjson_json::Error> for Error {
119 fn from(value: cityjson_json::Error) -> Self {
120 match value {
121 cityjson_json::Error::Json(error) => Self::Syntax(error.to_string()),
122 cityjson_json::Error::Utf8(error) => Self::Syntax(error.to_string()),
123 cityjson_json::Error::CityJson(error) => Self::CityJSON(error),
124 cityjson_json::Error::UnsupportedType(found) => Self::UnsupportedType(found),
125 cityjson_json::Error::UnsupportedVersion(found) => Self::UnsupportedVersion {
126 found,
127 supported: cityjson::CityJSONVersion::V2_0.to_string(),
128 },
129 cityjson_json::Error::MalformedRootObject(reason) => Self::Syntax(reason.to_owned()),
130 cityjson_json::Error::InvalidValue(reason) => Self::Import(reason),
131 cityjson_json::Error::UnsupportedFeature(feature) => {
132 Self::UnsupportedFeature(feature.to_owned())
133 }
134 cityjson_json::Error::UnresolvedCityObjectReference {
135 source_id,
136 target_id,
137 relation,
138 } => Self::Import(format!(
139 "unresolved CityObject {relation} reference from '{source_id}' to '{target_id}'"
140 )),
141 }
142 }
143}