# static_tile_fetcher.rs - source
Source of the Rust file `maplibre/src/io/static_tile_fetcher.rs`.
Keywords: rust, rustlang, rust-lang

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79

    //! Static tile fetcher

    use std::concat;
    use std::env;

    use include_dir::Dir;

    use crate::coords::TileCoords;
    use crate::error::Error;

    #[cfg(static_tiles)]
    use include_dir::include_dir;
    #[cfg(static_tiles)]
    static TILES: Dir = include_dir!("$OUT_DIR/extracted-tiles");
    #[cfg(not(static_tiles))]
    static TILES: Dir = Dir::new("/path", &[]);

    /// Load PBF files which were statically embedded in the `build.rs`
    #[derive(Default)]
    pub struct StaticTileFetcher;

    impl StaticTileFetcher {
        pub fn get_source_path() -> &'static str {
            concat!(env!("OUT_DIR"), "/extracted-tiles")
        }

        pub fn new() -> Self {
            Self {}
        }

        /// Fetch the tile static file asynchrounously and returns a vector of bytes or a network error if the file
        /// could not be fetched.
        pub async fn fetch_tile(&self, coords: &TileCoords) -> Result<Vec<u8>, Error> {
            self.sync_fetch_tile(coords)
        }

        /// Fetch the tile static file and returns a vector of bytes or a network error if the file
        /// could not be fetched.
        pub fn sync_fetch_tile(&self, coords: &TileCoords) -> Result<Vec<u8>, Error> {
            if TILES.entries().is_empty() {
                log::error!(
                    "There are not tiles statically embedded in this binary! StaticTileFetcher will \
                    not return any tiles!"
                )
            }

            let tile = TILES
                .get_file(format!("{}/{}/{}.{}", coords.z, coords.x, coords.y, "pbf"))
                .ok_or_else(|| {
                    Error::Network("Failed to load tile from within the binary".to_string())
                })?;
            Ok(Vec::from(tile.contents())) // TODO: Unnecessary copy
        }
    }

    #[cfg(test)]
    mod tests {
        use crate::style::source::TileAddressingScheme;

        use crate::coords::WorldTileCoords;

        use super::StaticTileFetcher;

        #[cfg(all(static_tiles, not(target_arch = "wasm32")))]
        #[tokio::test]
        async fn test_tiles_available() {
            const MUNICH_X: i32 = 17425;
            const MUNICH_Y: i32 = 11365;
            const MUNICH_Z: u8 = 15;

            let fetcher = StaticTileFetcher::new();
            assert!(fetcher.fetch_tile(&(0, 0, 0).into()).await.is_err()); // World overview
            let world_tile: WorldTileCoords = (MUNICH_X, MUNICH_Y, MUNICH_Z).into();
            assert!(fetcher
                .fetch_tile(&world_tile.into_tile(TileAddressingScheme::XYZ).unwrap())
                .await
                .is_ok()); // Maxvorstadt Munich
        }
    }