use crate::{ArcGISClient, Result, TileCoordinate};
use tracing::instrument;
use super::types::{FontStack, GlyphRange, VectorTileStyle};
#[derive(Clone)]
pub struct VectorTileServiceClient<'a> {
url: String,
client: &'a ArcGISClient,
}
impl<'a> VectorTileServiceClient<'a> {
pub fn new(url: impl Into<String>, client: &'a ArcGISClient) -> Self {
VectorTileServiceClient {
url: url.into(),
client,
}
}
#[instrument(skip(self), fields(level = tile.level(), row = tile.row(), col = tile.col()))]
pub async fn get_tile(&self, tile: &TileCoordinate) -> Result<Vec<u8>> {
tracing::debug!("Retrieving vector tile");
let tile_url = format!(
"{}/tile/{}/{}/{}.pbf",
self.url,
tile.level(),
tile.row(),
tile.col()
);
let response = self.client.http().get(&tile_url).send().await?;
let bytes = response.bytes().await?;
tracing::debug!(size = bytes.len(), "Tile retrieved");
Ok(bytes.to_vec())
}
#[instrument(skip(self), fields(tile_count = tiles.len()))]
pub async fn get_tiles(&self, tiles: &[TileCoordinate]) -> Result<Vec<Vec<u8>>> {
tracing::debug!("Retrieving multiple tiles");
let mut results = Vec::with_capacity(tiles.len());
let futures: Vec<_> = tiles.iter().map(|tile| self.get_tile(tile)).collect();
for future in futures {
results.push(future.await?);
}
tracing::debug!(count = results.len(), "All tiles retrieved");
Ok(results)
}
#[instrument(skip(self))]
pub async fn get_style(&self) -> Result<VectorTileStyle> {
tracing::debug!("Retrieving vector tile style");
let style_url = format!("{}/resources/styles/root.json", self.url);
let response = self.client.http().get(&style_url).send().await?;
let style: VectorTileStyle = response.json().await?;
tracing::debug!(
version = style.version(),
layer_count = style.layers().len(),
"Style retrieved"
);
Ok(style)
}
#[instrument(skip(self), fields(font = %font_stack.0, range = %range))]
pub async fn get_fonts(&self, font_stack: &FontStack, range: &GlyphRange) -> Result<Vec<u8>> {
tracing::debug!("Retrieving font glyphs");
let font_url = format!(
"{}/resources/fonts/{}/{}.pbf",
self.url,
font_stack.0,
range.format()
);
let response = self.client.http().get(&font_url).send().await?;
let bytes = response.bytes().await?;
tracing::debug!(size = bytes.len(), "Glyphs retrieved");
Ok(bytes.to_vec())
}
#[instrument(skip(self))]
pub async fn get_sprite_metadata(&self) -> Result<serde_json::Value> {
tracing::debug!("Retrieving sprite metadata");
let sprite_url = format!("{}/resources/sprites/sprite.json", self.url);
let response = self.client.http().get(&sprite_url).send().await?;
let metadata: serde_json::Value = response.json().await?;
tracing::debug!("Sprite metadata retrieved");
Ok(metadata)
}
#[instrument(skip(self))]
pub async fn get_sprite_image(&self) -> Result<Vec<u8>> {
tracing::debug!("Retrieving sprite image");
let sprite_url = format!("{}/resources/sprites/sprite.png", self.url);
let response = self.client.http().get(&sprite_url).send().await?;
let bytes = response.bytes().await?;
tracing::debug!(size = bytes.len(), "Sprite image retrieved");
Ok(bytes.to_vec())
}
}