martin_core/tiles/mbtiles/
source.rs1use std::fmt::{Debug, Formatter};
4use std::io;
5use std::path::PathBuf;
6use std::sync::Arc;
7
8use async_trait::async_trait;
9use log::trace;
10use martin_tile_utils::{TileCoord, TileData, TileInfo};
11use mbtiles::MbtilesPool;
12use tilejson::TileJSON;
13
14use crate::tiles::mbtiles::MbtilesError;
15use crate::tiles::{BoxedSource, MartinCoreResult, Source, UrlQuery};
16
17#[derive(Clone)]
19pub struct MbtSource {
20 id: String,
21 mbtiles: Arc<MbtilesPool>,
22 tilejson: TileJSON,
23 tile_info: TileInfo,
24}
25
26impl Debug for MbtSource {
27 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
28 write!(
29 f,
30 "MbtSource {{ id: {}, path: {:?} }}",
31 self.id,
32 self.mbtiles.as_ref()
33 )
34 }
35}
36
37impl MbtSource {
38 pub async fn new(id: String, path: PathBuf) -> Result<Self, MbtilesError> {
40 let mbt = MbtilesPool::open_readonly(&path)
41 .await
42 .map_err(|e| io::Error::other(format!("{e:?}: Cannot open file {}", path.display())))
43 .map_err(|e| MbtilesError::IoError(e, path.clone()))?;
44
45 let meta = mbt
46 .get_metadata()
47 .await
48 .map_err(|e| MbtilesError::InvalidMetadata(e.to_string(), path))?;
49
50 Ok(Self {
51 id,
52 mbtiles: Arc::new(mbt),
53 tilejson: meta.tilejson,
54 tile_info: meta.tile_info,
55 })
56 }
57}
58
59#[async_trait]
60impl Source for MbtSource {
61 fn get_id(&self) -> &str {
62 &self.id
63 }
64
65 fn get_tilejson(&self) -> &TileJSON {
66 &self.tilejson
67 }
68
69 fn get_tile_info(&self) -> TileInfo {
70 self.tile_info
71 }
72
73 fn clone_source(&self) -> BoxedSource {
74 Box::new(self.clone())
75 }
76
77 fn get_version(&self) -> Option<String> {
78 self.tilejson.version.clone()
79 }
80
81 fn benefits_from_concurrent_scraping(&self) -> bool {
82 false
84 }
85
86 async fn get_tile(
87 &self,
88 xyz: TileCoord,
89 _url_query: Option<&UrlQuery>,
90 ) -> MartinCoreResult<TileData> {
91 if let Some(tile) = self
92 .mbtiles
93 .get_tile(xyz.z, xyz.x, xyz.y)
94 .await
95 .map_err(|_| MbtilesError::AcquireConnError(self.id.clone()))?
96 {
97 Ok(tile)
98 } else {
99 trace!(
100 "Couldn't find tile data in {}/{}/{} of {}",
101 xyz.z, xyz.x, xyz.y, &self.id
102 );
103 Ok(Vec::new())
104 }
105 }
106}