diff options
author | Daniel Schadt <kingdread@gmx.de> | 2025-07-28 20:35:11 +0200 |
---|---|---|
committer | Daniel Schadt <kingdread@gmx.de> | 2025-07-28 20:35:11 +0200 |
commit | d839b9b7950c949eaddb967495f533e99a8dcafb (patch) | |
tree | d945b3055ba381af883ddc6954aa96da4d7a80cf | |
parent | 8247f7d7e1fe30debf738435b3cdccdd15c24e2f (diff) | |
download | hittekaart-d839b9b7950c949eaddb967495f533e99a8dcafb.tar.gz hittekaart-d839b9b7950c949eaddb967495f533e99a8dcafb.tar.bz2 hittekaart-d839b9b7950c949eaddb967495f533e99a8dcafb.zip |
implement sqlite output in hittekaart-py
We cannot use a Box<dyn Storage> anymore, because the Sqlite connection
is not thread-safe. Therefore, we use a normal enum and open the
connection late.
-rw-r--r-- | hittekaart-py/src/lib.rs | 55 |
1 files changed, 38 insertions, 17 deletions
diff --git a/hittekaart-py/src/lib.rs b/hittekaart-py/src/lib.rs index 9f4bd8d..4b67777 100644 --- a/hittekaart-py/src/lib.rs +++ b/hittekaart-py/src/lib.rs @@ -7,6 +7,7 @@ use std::error::Error; use std::ffi::OsStr; use std::fmt::Write as _; use std::os::unix::ffi::OsStrExt as _; +use std::path::PathBuf; create_exception!(hittekaart_py, HitteError, pyo3::exceptions::PyException); @@ -61,20 +62,45 @@ impl Track { } } -#[pyclass] -struct Storage { - inner: Box<dyn hittekaart::storage::Storage + Send + Sync>, +#[derive(Debug, Clone, PartialEq, Eq)] +enum StorageType { + Folder(PathBuf), + Sqlite(PathBuf), } +#[pyclass] +#[derive(Debug, Clone, PartialEq, Eq)] +struct Storage(StorageType); + #[pymethods] impl Storage { #[staticmethod] #[pyo3(name = "Folder")] fn folder(path: &[u8]) -> Self { let path = OsStr::from_bytes(path); - let storage = hittekaart::storage::Folder::new(path.into()); - Storage { - inner: Box::new(storage), + Storage(StorageType::Folder(path.into())) + } + + #[staticmethod] + #[pyo3(name = "Sqlite")] + fn sqlite(path: &[u8]) -> Self { + let path = OsStr::from_bytes(path); + Storage(StorageType::Sqlite(path.into())) + } +} + +impl Storage { + fn open(&self) -> PyResult<Box<dyn hittekaart::storage::Storage>> { + match self.0 { + StorageType::Folder(ref path) => { + let storage = hittekaart::storage::Folder::new(path.clone()); + Ok(Box::new(storage)) + } + StorageType::Sqlite(ref path) => { + let storage = hittekaart::storage::Sqlite::connect(path.clone()) + .map_err(|e| err_to_py(&e))?; + Ok(Box::new(storage)) + } } } } @@ -108,7 +134,7 @@ fn generate( } if let Ok(r) = renderer.downcast::<HeatmapRenderer>() { - do_generate(tracks, &r.borrow().inner, &mut storage.borrow_mut()) + do_generate(tracks, &r.borrow().inner, &mut *storage.borrow().open()?) } else { Err(PyTypeError::new_err("Expected a HeatmapRenderer")) } @@ -117,28 +143,23 @@ fn generate( fn do_generate<R: Renderer>( tracks: Vec<Vec<Coordinates>>, renderer: &R, - storage: &mut Storage, + storage: &mut dyn hittekaart::storage::Storage, ) -> PyResult<()> { - storage.inner.prepare().map_err(|e| err_to_py(&e))?; + storage.prepare().map_err(|e| err_to_py(&e))?; for zoom in 0..=19 { let counter = renderer::prepare(renderer, zoom, &tracks, || Ok(())).map_err(|e| err_to_py(&e))?; - storage - .inner - .prepare_zoom(zoom) - .map_err(|e| err_to_py(&e))?; + storage.prepare_zoom(zoom).map_err(|e| err_to_py(&e))?; renderer::colorize(renderer, counter, |rendered_tile| { - storage - .inner - .store(zoom, rendered_tile.x, rendered_tile.y, &rendered_tile.data)?; + storage.store(zoom, rendered_tile.x, rendered_tile.y, &rendered_tile.data)?; Ok(()) }) .map_err(|e| err_to_py(&e))?; } - storage.inner.finish().map_err(|e| err_to_py(&e))?; + storage.finish().map_err(|e| err_to_py(&e))?; Ok(()) } |