Skip to main content

everymap_providers_mapbox/domain/tiling/
mod.rs

1use crate::client::MapBoxClient;
2use async_trait::async_trait;
3use everymap_core::domains::tiling::{TileOptions, TileProvider, TileResponse};
4use everymap_core::error::EveryMapResult;
5use std::sync::Arc;
6
7const MAP_BASE_URL: &str = "https://api.mapbox.com";
8
9/// Implementation of TileProvider for MapBox Vector/Raster Tiles API.
10pub struct MapBoxTileProvider {
11    pub(crate) client: Arc<MapBoxClient>,
12    pub(crate) base_url: String,
13}
14
15impl MapBoxTileProvider {
16    pub fn new(client: Arc<MapBoxClient>) -> Self {
17        Self {
18            client,
19            base_url: MAP_BASE_URL.to_string(),
20        }
21    }
22
23    pub fn with_base_url(client: Arc<MapBoxClient>, base_url: String) -> Self {
24        Self { client, base_url }
25    }
26}
27
28#[async_trait]
29impl TileProvider for MapBoxTileProvider {
30    async fn get_tile(
31        &self,
32        z: u32,
33        x: u32,
34        y: u32,
35        options: &TileOptions,
36    ) -> EveryMapResult<TileResponse> {
37        let tileset_id = options
38            .provider_extra
39            .as_ref()
40            .and_then(|e| e.get("tileset_id"))
41            .and_then(|v| v.as_str())
42            .unwrap_or("mapbox.mapbox-streets-v8");
43        let format = options.format.as_deref().unwrap_or("mvt");
44
45        let url = format!(
46            "{}/v4/{}/{}/{}/{}.{}",
47            self.base_url, tileset_id, z, x, y, format
48        );
49
50        let builder = self.client.build_request(reqwest::Method::GET, &url);
51
52        let response = self.client.request(builder).await?;
53
54        let content_type = response
55            .headers()
56            .get("content-type")
57            .and_then(|v| v.to_str().ok())
58            .map(|s| s.split(';').next().unwrap_or(s).trim().to_string());
59
60        let data = response.bytes().await?.to_vec();
61
62        Ok(TileResponse { data, content_type })
63    }
64}