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