1use std::str::FromStr;
2
3use serde_json::{Map, Value};
4
5use crate::tile_tuple::TileTuple;
6use crate::{Tile, UtilesCoreError};
7
8impl From<(u8, u32, u32)> for Tile {
13 fn from(xyz: (u8, u32, u32)) -> Self {
14 Self {
15 z: xyz.0,
16 x: xyz.1,
17 y: xyz.2,
18 }
19 }
20}
21
22impl From<(u32, u32, u8)> for Tile {
23 fn from(xyz: (u32, u32, u8)) -> Self {
24 Self {
25 x: xyz.0,
26 y: xyz.1,
27 z: xyz.2,
28 }
29 }
30}
31
32impl From<TileTuple> for Tile {
33 fn from(xyz: TileTuple) -> Self {
34 Self {
35 x: xyz.0,
36 y: xyz.1,
37 z: xyz.2,
38 }
39 }
40}
41
42impl From<Tile> for (u32, u32, u8) {
43 fn from(tile: Tile) -> Self {
44 (tile.x, tile.y, tile.z)
45 }
46}
47
48impl TryFrom<(u32, u32, u32)> for Tile {
49 type Error = UtilesCoreError;
50
51 fn try_from(xyz: (u32, u32, u32)) -> Result<Self, Self::Error> {
52 let z = u8::try_from(xyz.0)?;
53 if z > 30 {
54 return Err(UtilesCoreError::InvalidTile(format!(
55 "Invalid tile zoom level: {}. Maximum is 30.",
56 xyz.2
57 )));
58 }
59 let max_xy = (1 << z) - 1;
60 if xyz.1 > max_xy || xyz.2 > max_xy {
61 Err(UtilesCoreError::InvalidTile(format!(
62 "Invalid tile coordinates: x: {}, y: {}, z: {}",
63 xyz.0, xyz.1, xyz.2
64 )))
65 } else {
66 Ok(Self {
67 x: xyz.0,
68 y: xyz.1,
69 z,
70 })
71 }
72 }
73}
74
75impl TryFrom<&str> for Tile {
76 type Error = UtilesCoreError;
77
78 fn try_from(s: &str) -> Result<Self, Self::Error> {
79 let res = Self::from_str(s);
80 match res {
81 Ok(tile) => Ok(tile),
82 Err(e) => Err(UtilesCoreError::TileParseError(e.to_string())),
83 }
84 }
85}
86
87impl TryFrom<Value> for Tile {
88 type Error = UtilesCoreError;
89
90 fn try_from(val: Value) -> Result<Self, Self::Error> {
91 Self::try_from(&val)
92 }
93}
94
95impl TryFrom<(u64, u64, u64)> for Tile {
96 type Error = UtilesCoreError;
97
98 fn try_from(tuple: (u64, u64, u64)) -> Result<Self, Self::Error> {
99 let x = u32::try_from(tuple.0).map_err(|_| {
100 UtilesCoreError::InvalidTile(format!(
101 "({},{},{})",
102 tuple.0, tuple.1, tuple.2
103 ))
104 })?;
105 let y = u32::try_from(tuple.1).map_err(|_| {
106 UtilesCoreError::InvalidTile(format!(
107 "({},{},{})",
108 tuple.0, tuple.1, tuple.2
109 ))
110 })?;
111 let z = u8::try_from(tuple.2).map_err(|_| {
112 UtilesCoreError::InvalidTile(format!(
113 "({},{},{})",
114 tuple.0, tuple.1, tuple.2
115 ))
116 })?;
117 Ok(Self::new(x, y, z))
118 }
119}
120
121impl TryFrom<&Vec<Value>> for Tile {
122 type Error = UtilesCoreError;
123
124 fn try_from(arr: &Vec<Value>) -> Result<Self, Self::Error> {
125 if arr.len() < 3 {
126 Err(UtilesCoreError::InvalidJson(
127 serde_json::to_string(&arr).unwrap_or_default(),
128 ))
129 } else {
130 let x = arr[0].as_u64().ok_or_else(|| {
131 UtilesCoreError::InvalidJson(
132 serde_json::to_string(&arr).unwrap_or_default(),
133 )
134 })?;
135 let y = arr[1].as_u64().ok_or_else(|| {
136 UtilesCoreError::InvalidJson(
137 serde_json::to_string(&arr).unwrap_or_default(),
138 )
139 })?;
140 let z = arr[2].as_u64().ok_or_else(|| {
141 UtilesCoreError::InvalidJson(
142 serde_json::to_string(&arr).unwrap_or_default(),
143 )
144 })?;
145 Self::try_from((x, y, z))
146 }
147 }
148}
149
150impl TryFrom<&Value> for Tile {
151 type Error = UtilesCoreError;
152
153 fn try_from(val: &Value) -> Result<Self, Self::Error> {
154 match val {
155 Value::Array(v) => {
156 let t = Self::try_from(v)?;
157 Ok(t)
158 }
159 Value::Object(v) => {
160 if v.contains_key("x") && v.contains_key("y") && v.contains_key("z") {
161 let x = v["x"].as_u64().ok_or_else(|| {
162 UtilesCoreError::InvalidJson(
163 serde_json::to_string(&v)
164 .expect("Invalid json object for Tile from Value"),
165 )
166 })?;
167 let y = v["y"].as_u64().ok_or_else(|| {
168 UtilesCoreError::InvalidJson(
169 serde_json::to_string(&v)
170 .expect("Invalid json object for Tile from Value"),
171 )
172 })?;
173 let z = v["z"].as_u64().ok_or_else(|| {
174 UtilesCoreError::InvalidJson(
175 serde_json::to_string(&v)
176 .expect("Invalid json object for Tile from Value"),
177 )
178 })?;
179 Self::try_from((x, y, z))
180 } else if v.contains_key("tile")
181 && v["tile"].is_array()
182 && v["tile"]
183 .as_array()
184 .expect("Unable to get tile array from Value")
185 .len()
186 == 3
187 {
188 let tuple = serde_json::from_value::<TileTuple>(v["tile"].clone())?;
189 Ok(Self::from(tuple))
190 } else {
191 Err(UtilesCoreError::InvalidJson(
192 serde_json::to_string(&v)
193 .expect("Invalid json object for Tile from Value"),
194 ))
195 }
196 }
197 _ => Err(UtilesCoreError::InvalidJson(val.to_string())),
198 }
199 }
200}
201
202impl TryFrom<&Map<String, Value>> for Tile {
203 type Error = UtilesCoreError;
204
205 fn try_from(map: &Map<String, Value>) -> Result<Self, Self::Error> {
206 let x = u32::try_from(map["x"].as_u64().ok_or_else(|| {
207 UtilesCoreError::InvalidJson(
208 serde_json::to_string(&map).unwrap_or_default(),
209 )
210 })?)
211 .map_err(|_| {
212 UtilesCoreError::InvalidJson(
213 serde_json::to_string(&map).unwrap_or_default(),
214 )
215 })?;
216 let y = u32::try_from(map["y"].as_u64().ok_or_else(|| {
217 UtilesCoreError::InvalidJson(
218 serde_json::to_string(&map).unwrap_or_default(),
219 )
220 })?)
221 .map_err(|_| {
222 UtilesCoreError::InvalidJson(
223 serde_json::to_string(&map).unwrap_or_default(),
224 )
225 })?;
226 let z = u8::try_from(map["z"].as_u64().ok_or_else(|| {
227 UtilesCoreError::InvalidJson(
228 serde_json::to_string(&map).unwrap_or_default(),
229 )
230 })?)
231 .map_err(|_| {
232 UtilesCoreError::InvalidJson(
233 serde_json::to_string(&map).unwrap_or_default(),
234 )
235 })?;
236 Ok(Self::new(x, y, z))
237 }
238}