utiles_core/
from.rs

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