Skip to main content

utiles_core/
from.rs

1use std::str::FromStr;
2
3use serde_json::{Map, Value};
4
5use crate::tile_tuple::TileTuple;
6use crate::{Tile, UtilesCoreError};
7
8// =============================================================================
9// From ... for TILE
10// =============================================================================
11
12impl 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}