tile_grid/
registry.rs

1use crate::tile_matrix_set::TileMatrixSetOps;
2use crate::tms::Tms;
3use ogcapi_types::tiles::TileMatrixSet;
4use once_cell::sync::OnceCell;
5use std::collections::HashMap;
6
7/// Registry of tile matrix sets
8#[derive(Clone)]
9pub struct TileMatrixSets {
10    // Registry containing Tms is not supported because of Proj:
11    // trait `Send` is not implemented for `*mut proj_sys::PJ_AREA`
12    coll: HashMap<String, TileMatrixSet>,
13}
14
15#[derive(thiserror::Error, Debug)]
16pub enum RegistryError {
17    #[error("Tile Matrix set not found: `{0}`")]
18    TmsNotFound(String),
19    #[error("`{0}` is already a registered TMS")]
20    TmsAlreadyRegistered(String),
21    #[error(transparent)]
22    TmsError(#[from] crate::tms::TmsError),
23}
24
25impl Default for TileMatrixSets {
26    fn default() -> Self {
27        Self::new()
28    }
29}
30
31impl TileMatrixSets {
32    pub fn new() -> Self {
33        Self {
34            coll: HashMap::new(),
35        }
36    }
37
38    pub fn get(&self, id: &str) -> Result<&TileMatrixSet, RegistryError> {
39        self.coll
40            .get(id)
41            .ok_or(RegistryError::TmsNotFound(id.to_string()))
42    }
43
44    pub fn lookup(&self, id: &str) -> Result<Tms, RegistryError> {
45        self.get(id)?.try_into().map_err(Into::into)
46    }
47
48    pub fn list(&self) -> impl Iterator<Item = &String> {
49        self.coll.keys()
50    }
51
52    pub fn register(
53        &mut self,
54        custom_tms: Vec<TileMatrixSet>,
55        overwrite: bool,
56    ) -> Result<(), RegistryError> {
57        for tms in custom_tms {
58            if self.coll.contains_key(&tms.id) {
59                if overwrite {
60                    self.coll.insert(tms.id.clone(), tms);
61                } else {
62                    return Err(RegistryError::TmsAlreadyRegistered(tms.id));
63                }
64            } else {
65                self.coll.insert(tms.id.clone(), tms);
66            }
67        }
68        Ok(())
69    }
70}
71
72/// Global registry of tile matrix sets
73pub fn tms() -> &'static TileMatrixSets {
74    static TMS: OnceCell<TileMatrixSets> = OnceCell::new();
75    TMS.get_or_init(|| {
76        let mut sets = TileMatrixSets::new();
77        let tms = vec![
78            #[cfg(feature = "projtransform")]
79            include_str!("../data/CanadianNAD83_LCC.json"),
80            //include_str!("../data/CDB1GlobalGrid.json"), // Error("missing field `coalesc`", line: 19, column: 67)
81            #[cfg(feature = "projtransform")]
82            include_str!("../data/EuropeanETRS89_LAEAQuad.json"),
83            //include_str!("../data/GNOSISGlobalGrid.json"), // Error("missing field `coalesc`", line: 31, column: 66)
84            #[cfg(feature = "projtransform")]
85            include_str!("../data/UPSAntarcticWGS84Quad.json"),
86            #[cfg(feature = "projtransform")]
87            include_str!("../data/UPSArcticWGS84Quad.json"),
88            #[cfg(feature = "projtransform")]
89            include_str!("../data/UTM31WGS84Quad.json"),
90            include_str!("../data/WebMercatorQuad.json"),
91            include_str!("../data/WGS1984Quad.json"),
92            //include_str!("../data/WorldCRS84Quad.json"), // conflicts with WGS1984Quad
93            include_str!("../data/WorldMercatorWGS84Quad.json"),
94        ]
95        .into_iter()
96        .map(|data| TileMatrixSet::from_json(data).unwrap())
97        .collect::<Vec<_>>();
98        sets.register(tms, false).unwrap();
99        // user_tms_dir = os.environ.get("TILEMATRIXSET_DIRECTORY", None)
100        // if user_tms_dir:
101        //     tms_paths.extend(list(pathlib.Path(user_tms_dir).glob("*.json")))
102        sets
103    })
104}