diff --git a/Cargo.lock b/Cargo.lock index 44b92ca3..f0899a96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1828,7 +1828,9 @@ dependencies = [ "futures", "log", "martin-tile-utils", + "serde", "serde_json", + "serde_yaml", "sqlite-hashes", "sqlx", "thiserror", diff --git a/docs/src/tools.md b/docs/src/tools.md index 68bccde1..ff71bafc 100644 --- a/docs/src/tools.md +++ b/docs/src/tools.md @@ -7,6 +7,13 @@ A small utility that allows users to interact with the `*.mbtiles` files from th This tool can be installed by compiling the latest released version with `cargo install martin-mbtiles`, or by downloading a pre-built binary from the [releases page](https://github.com/maplibre/martin/releases/latest). +### meta-all +Print all metadata values to stdout, as well as the results of tile detection. The format of the values printed is not stable, and should only be used for visual inspection. + +```shell +mbtiles meta-all my_file.mbtiles +``` + ### meta-get Retrieve raw metadata value by its name. The value is printed to stdout without any modifications. For example, to get the `description` value from an mbtiles file: diff --git a/martin-mbtiles/Cargo.toml b/martin-mbtiles/Cargo.toml index 5be2b10a..3392c25a 100644 --- a/martin-mbtiles/Cargo.toml +++ b/martin-mbtiles/Cargo.toml @@ -21,6 +21,7 @@ rustls = ["sqlx/runtime-tokio-rustls"] futures.workspace = true log.workspace = true martin-tile-utils.workspace = true +serde.workspace = true serde_json.workspace = true sqlx.workspace = true thiserror.workspace = true @@ -29,6 +30,7 @@ tilejson.workspace = true # Bin dependencies anyhow = { workspace = true, optional = true } clap = { workspace = true, optional = true } +serde_yaml.workspace = true sqlite-hashes.workspace = true tokio = { workspace = true, features = ["rt-multi-thread"], optional = true } diff --git a/martin-mbtiles/src/bin/main.rs b/martin-mbtiles/src/bin/main.rs index 0fad74f8..53ff6239 100644 --- a/martin-mbtiles/src/bin/main.rs +++ b/martin-mbtiles/src/bin/main.rs @@ -24,12 +24,12 @@ pub struct Args { #[derive(Subcommand, PartialEq, Eq, Debug)] enum Commands { - // /// Prints all values in the metadata table. - // #[command(name = "meta-all")] - // MetaAll { - // /// MBTiles file to read from - // file: PathBuf, - // }, + /// Prints all values in the metadata table in a free-style, unstable YAML format + #[command(name = "meta-all")] + MetaAll { + /// MBTiles file to read from + file: PathBuf, + }, /// Gets a single value from the MBTiles metadata table. #[command(name = "meta-get")] MetaGetValue { @@ -78,6 +78,9 @@ async fn main() -> Result<()> { let args = Args::parse(); match args.command { + Commands::MetaAll { file } => { + meta_print_all(file.as_path()).await?; + } Commands::MetaGetValue { file, key } => { meta_get_value(file.as_path(), &key).await?; } @@ -105,6 +108,15 @@ async fn main() -> Result<()> { Ok(()) } +async fn meta_print_all(file: &Path) -> Result<()> { + let mbt = Mbtiles::new(file)?; + let opt = SqliteConnectOptions::new().filename(file).read_only(true); + let mut conn = SqliteConnection::connect_with(&opt).await?; + let metadata = mbt.get_metadata(&mut conn).await?; + println!("{}", serde_yaml::to_string(&metadata)?); + Ok(()) +} + async fn meta_get_value(file: &Path, key: &str) -> Result<()> { let mbt = Mbtiles::new(file)?; let opt = SqliteConnectOptions::new().filename(file).read_only(true); diff --git a/martin-mbtiles/src/mbtiles.rs b/martin-mbtiles/src/mbtiles.rs index 2bde122b..1c30db24 100644 --- a/martin-mbtiles/src/mbtiles.rs +++ b/martin-mbtiles/src/mbtiles.rs @@ -11,6 +11,8 @@ use clap::ValueEnum; use futures::TryStreamExt; use log::{debug, info, warn}; use martin_tile_utils::{Format, TileInfo}; +use serde::ser::SerializeStruct; +use serde::Serialize; use serde_json::{Value as JSONValue, Value}; use sqlite_hashes::register_md5_function; use sqlite_hashes::rusqlite::{Connection as RusqliteConnection, Connection, OpenFlags}; @@ -26,15 +28,33 @@ use crate::MbtError::{ AggHashMismatch, AggHashValueNotFound, FailedIntegrityCheck, InvalidTileData, }; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize)] pub struct Metadata { pub id: String, + #[serde(serialize_with = "serialize_ti")] pub tile_info: TileInfo, pub layer_type: Option, pub tilejson: TileJSON, pub json: Option, } +#[allow(clippy::trivially_copy_pass_by_ref)] +fn serialize_ti(ti: &TileInfo, serializer: S) -> Result +where + S: serde::Serializer, +{ + let mut s = serializer.serialize_struct("TileInfo", 2)?; + s.serialize_field("format", &ti.format.to_string())?; + s.serialize_field( + "encoding", + match ti.encoding.content_encoding() { + None => "", + Some(v) => v, + }, + )?; + s.end() +} + #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "cli", derive(ValueEnum))] pub enum MbtType { diff --git a/tests/expected/mbtiles/help.txt b/tests/expected/mbtiles/help.txt index abb9e81f..a7f0896a 100644 --- a/tests/expected/mbtiles/help.txt +++ b/tests/expected/mbtiles/help.txt @@ -3,6 +3,7 @@ A utility to work with .mbtiles file content Usage: mbtiles Commands: + meta-all Prints all values in the metadata table in a free-style, unstable YAML format meta-get Gets a single value from the MBTiles metadata table meta-set Sets a single value in the MBTiles' file metadata table or deletes it if no value copy Copy tiles from one mbtiles file to another diff --git a/tests/expected/mbtiles/meta-all.txt b/tests/expected/mbtiles/meta-all.txt new file mode 100644 index 00000000..2949d92f --- /dev/null +++ b/tests/expected/mbtiles/meta-all.txt @@ -0,0 +1,112 @@ +id: world_cities +tile_info: + format: mvt + encoding: gzip +layer_type: overlay +tilejson: + tilejson: 3.0.0 + tiles: [] + vector_layers: + - id: cities + fields: + name: String + description: '' + maxzoom: 6 + minzoom: 0 + bounds: + - -123.12359 + - -37.818085 + - 174.763027 + - 59.352706 + center: + - -75.9375 + - 38.788894 + - 6 + description: Major cities from Natural Earth data + maxzoom: 6 + minzoom: 0 + name: Major cities from Natural Earth data + version: '2' + format: pbf +json: + tilestats: + layerCount: 1 + layers: + - attributeCount: 1 + attributes: + - attribute: name + count: 68 + type: string + values: + - Addis Ababa + - Amsterdam + - Athens + - Atlanta + - Auckland + - Baghdad + - Bangalore + - Bangkok + - Beijing + - Berlin + - Bogota + - Buenos Aires + - Cairo + - Cape Town + - Caracas + - Casablanca + - Chengdu + - Chicago + - Dakar + - Denver + - Dubai + - Geneva + - Hong Kong + - Houston + - Istanbul + - Jakarta + - Johannesburg + - Kabul + - Kiev + - Kinshasa + - Kolkata + - Lagos + - Lima + - London + - Los Angeles + - Madrid + - Manila + - Melbourne + - Mexico City + - Miami + - Monterrey + - Moscow + - Mumbai + - Nairobi + - New Delhi + - New York + - Paris + - Rio de Janeiro + - Riyadh + - Rome + - San Francisco + - Santiago + - Seoul + - Shanghai + - Singapore + - Stockholm + - Sydney + - São Paulo + - Taipei + - Tashkent + - Tehran + - Tokyo + - Toronto + - Vancouver + - Vienna + - Washington, D.C. + - Ürümqi + - Ōsaka + count: 68 + geometry: Point + layer: cities + diff --git a/tests/expected/mbtiles/meta-all_help.txt b/tests/expected/mbtiles/meta-all_help.txt new file mode 100644 index 00000000..83c19912 --- /dev/null +++ b/tests/expected/mbtiles/meta-all_help.txt @@ -0,0 +1,9 @@ +Prints all values in the metadata table in a free-style, unstable YAML format + +Usage: mbtiles meta-all + +Arguments: + MBTiles file to read from + +Options: + -h, --help Print help diff --git a/tests/test.sh b/tests/test.sh index e29e5919..846e1a3d 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -288,6 +288,8 @@ if [[ "$MBTILES_BIN" != "-" ]]; then set -x $MBTILES_BIN --help 2>&1 | tee "$TEST_OUT_DIR/help.txt" + $MBTILES_BIN meta-all --help 2>&1 | tee "$TEST_OUT_DIR/meta-all_help.txt" + $MBTILES_BIN meta-all ./tests/fixtures/files/world_cities.mbtiles 2>&1 | tee "$TEST_OUT_DIR/meta-all.txt" $MBTILES_BIN meta-get --help 2>&1 | tee "$TEST_OUT_DIR/meta-get_help.txt" $MBTILES_BIN meta-get ./tests/fixtures/files/world_cities.mbtiles name 2>&1 | tee "$TEST_OUT_DIR/meta-get_name.txt" $MBTILES_BIN meta-get ./tests/fixtures/files/world_cities.mbtiles missing_value 2>&1 | tee "$TEST_OUT_DIR/meta-get_missing_value.txt"