diff --git a/.editorconfig b/.editorconfig index d86c1352..789acece 100644 --- a/.editorconfig +++ b/.editorconfig @@ -32,12 +32,12 @@ indent_size = 4 [*.{js,jsx,ts,tsx,cjs,mjs,cts,mts}] indent_style = space indent_size = 2 -max_line_length = 120 +max_line_length = 80 [*.{graphql,gqp}] indent_style = space indent_size = 2 -max_line_length = 120 +max_line_length = 80 [*.{json,json5,ndjson,jsonc,webmanifest}] indent_size = 2 @@ -57,6 +57,7 @@ indent_size = 2 # Misc webfiles [*.{htm,html,js,jsm,ts,tsx,cjs,cts,ctsx,mjs,mts,mtsx,css,sass,scss,less,pcss,svg,vue}] indent_size = 2 +max_line_length = 80 # Visual studio solution file(s) [*.sln] diff --git a/.gitignore b/.gitignore index 655f2c78..176915bb 100644 --- a/.gitignore +++ b/.gitignore @@ -195,3 +195,6 @@ target/ .hypothesis/ file.py *.so + +# testing data +blue-marble/ diff --git a/Cargo.lock b/Cargo.lock index 2f4f93e4..085ce229 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,6 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", + "getrandom", "once_cell", "version_check", "zerocopy", @@ -44,6 +45,21 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "0.6.4" @@ -79,7 +95,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -89,7 +105,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -107,6 +123,36 @@ dependencies = [ "num-traits", ] +[[package]] +name = "async-trait" +version = "0.1.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atomic-write-file" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae364a6c1301604bbc6dfbf8c385c47ff82301dd01eef506195a029196d8d04" +dependencies = [ + "nix", + "rand", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -128,6 +174,18 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bitflags" version = "1.3.2" @@ -139,6 +197,18 @@ name = "bitflags" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +dependencies = [ + "serde", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] [[package]] name = "bstr" @@ -150,6 +220,18 @@ dependencies = [ "serde", ] +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.5.0" @@ -171,11 +253,23 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "windows-targets 0.48.5", +] + [[package]] name = "clap" -version = "4.4.7" +version = "4.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272" dependencies = [ "clap_builder", "clap_derive", @@ -193,9 +287,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.7" +version = "4.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1" dependencies = [ "anstream", "anstyle", @@ -212,7 +306,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -227,11 +321,228 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "const-oid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "cpufeatures" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "deadpool" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb84100978c1c7b37f09ed3ce3e5f843af02c2a2c431bae5b19230dad2c1b490" +dependencies = [ + "async-trait", + "deadpool-runtime", + "num_cpus", + "tokio", +] + +[[package]] +name = "deadpool-runtime" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63dfa964fe2a66f3fde91fc70b267fe193d822c7e603e2a675a49a7f46ad3f49" +dependencies = [ + "tokio", +] + +[[package]] +name = "deadpool-sqlite" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8010e36e12f3be22543a5e478b4af20aeead9a700dd69581a5e050a070fc22c" +dependencies = [ + "deadpool", + "deadpool-sync", + "rusqlite", +] + +[[package]] +name = "deadpool-sync" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8db70494c13cae4ce67b4b4dafdaf828cf0df7237ab5b9e2fcabee4965d0a0a" +dependencies = [ + "deadpool-runtime", + "tracing", +] + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "dup-indexer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d97b917c67f654f51144fa5060e7709b6d97a17198572a2216d63fecc4ef5b52" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +dependencies = [ + "serde", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "fallible-iterator" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fallible-streaming-iterator" @@ -249,16 +560,158 @@ dependencies = [ ] [[package]] -name = "fnv" -version = "1.0.7" +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "finl_unicode" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "spin 0.9.8", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" + +[[package]] +name = "futures-executor" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "futures-io" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" + +[[package]] +name = "futures-macro" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "futures-sink" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" + +[[package]] +name = "futures-task" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" + +[[package]] +name = "futures-util" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] [[package]] name = "geo-types" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9705398c5c7b26132e74513f4ee7c1d7dafd786004991b375c172be2be0eecaa" +checksum = "567495020b114f1ce9bed679b29975aa0bfae06ac22beacd5cfde5dabe7b05d6" dependencies = [ "approx", "num-traits", @@ -278,30 +731,59 @@ dependencies = [ "thiserror", ] +[[package]] +name = "geozero" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b1b9a1eeae9ad09e12ec50243956105184b26440f81f978cd3aae009b214d4d" +dependencies = [ + "dup-indexer", + "geo-types", + "geojson", + "log", + "prost", + "prost-build", + "scroll", + "serde_json", + "thiserror", + "wkt", +] + +[[package]] +name = "getrandom" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "globset" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick", "bstr", - "fnv", "log", - "regex", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", ] [[package]] name = "hashbrown" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ "ahash", "allocator-api2", @@ -321,6 +803,9 @@ name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] [[package]] name = "hermit-abi" @@ -328,46 +813,151 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "ignore" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +checksum = "747ad1b4ae841a78e8aba0d63adbfbeaea26b517b63705d47856b73015d27060" dependencies = [ + "crossbeam-deque", "globset", - "lazy_static", "log", "memchr", - "regex", + "regex-automata 0.4.3", "same-file", - "thread_local", "walkdir", "winapi-util", ] +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "indoc" version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +[[package]] +name = "js-sys" +version = "0.3.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libm" @@ -377,15 +967,21 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libsqlite3-sys" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" +checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" dependencies = [ "cc", "pkg-config", "vcpkg", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" + [[package]] name = "lock_api" version = "0.4.11" @@ -411,6 +1007,16 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + [[package]] name = "memchr" version = "2.6.4" @@ -418,42 +1024,113 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] -name = "memoffset" -version = "0.9.0" +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.4.1", + "cfg-if", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ - "autocfg", + "overload", + "winapi", ] [[package]] -name = "miniz_oxide" -version = "0.7.1" +name = "num-bigint-dig" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" dependencies = [ - "adler", + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", ] [[package]] -name = "mio" -version = "0.8.9" +name = "num-integer" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ - "libc", - "wasi", - "windows-sys", + "autocfg", + "num-traits", ] [[package]] -name = "nu-ansi-term" -version = "0.46.0" +name = "num-iter" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ - "overload", - "winapi", + "autocfg", + "num-integer", + "num-traits", ] [[package]] @@ -517,7 +1194,38 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "petgraph" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +dependencies = [ + "fixedbitset", + "indexmap", ] [[package]] @@ -526,21 +1234,124 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +dependencies = [ + "bytes", + "heck", + "itertools 0.10.5", + "lazy_static", + "log", + "multimap", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn 1.0.109", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost", +] + [[package]] name = "pyo3" version = "0.20.0" @@ -587,7 +1398,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -599,7 +1410,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -627,6 +1438,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -680,11 +1521,31 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "rsa" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af6c4b23d99685a1408194da11270ef8e9809aff951cc70ec9b17350b087e474" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rusqlite" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" +checksum = "a78046161564f5e7cd9008aff3b2990b3850dc8e0349119b98e8f251e099f24d" dependencies = [ "bitflags 2.4.1", "fallible-iterator", @@ -700,6 +1561,19 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustix" +version = "0.38.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + [[package]] name = "ryu" version = "1.0.15" @@ -721,31 +1595,37 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scroll" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" + [[package]] name = "serde" -version = "1.0.190" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.190" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -763,48 +1643,332 @@ dependencies = [ ] [[package]] -name = "serde_tuple_macros" -version = "0.5.0" +name = "serde_tuple_macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4076151d1a2b688e25aaf236997933c66e18b870d0369f8b248b8ab2be630d7e" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlformat" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85" +dependencies = [ + "itertools 0.11.0", + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dba03c279da73694ef99763320dea58b51095dfe87d001b1d4b5fe78ba8763cf" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d84b0a3c3739e220d94b3239fd69fb1f74bc36e16643423bd99de3b43c21bfbd" +dependencies = [ + "ahash", + "atoi", + "byteorder", + "bytes", + "crc", + "crossbeam-queue", + "dotenvy", + "either", + "event-listener", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashlink", + "hex", + "indexmap", + "log", + "memchr", + "once_cell", + "paste", + "percent-encoding", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlformat", + "thiserror", + "tokio", + "tokio-stream", + "tracing", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89961c00dc4d7dffb7aee214964b065072bff69e36ddb9e2c107541f75e4f2a5" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 1.0.109", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4076151d1a2b688e25aaf236997933c66e18b870d0369f8b248b8ab2be630d7e" +checksum = "d0bd4519486723648186a08785143599760f7cc81c52334a55d6a83ea1e20841" dependencies = [ + "atomic-write-file", + "dotenvy", + "either", + "heck", + "hex", + "once_cell", "proc-macro2", "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-sqlite", "syn 1.0.109", + "tempfile", + "tokio", + "url", ] [[package]] -name = "sharded-slab" -version = "0.1.7" +name = "sqlx-mysql" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" dependencies = [ - "lazy_static", + "atoi", + "base64", + "bitflags 2.4.1", + "byteorder", + "bytes", + "crc", + "digest", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", ] [[package]] -name = "signal-hook-registry" -version = "1.4.1" +name = "sqlx-postgres" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" dependencies = [ - "libc", + "atoi", + "base64", + "bitflags 2.4.1", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand", + "serde", + "serde_json", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", ] [[package]] -name = "smallvec" -version = "1.11.1" +name = "sqlx-sqlite" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" +dependencies = [ + "atoi", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "sqlx-core", + "tracing", + "url", + "urlencoding", +] [[package]] -name = "socket2" -version = "0.5.5" +name = "stringprep" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" dependencies = [ - "libc", - "windows-sys", + "finl_unicode", + "unicode-bidi", + "unicode-normalization", ] [[package]] @@ -813,6 +1977,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + [[package]] name = "syn" version = "1.0.109" @@ -826,9 +1996,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -841,6 +2011,19 @@ version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" +[[package]] +name = "tempfile" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "thiserror" version = "1.0.50" @@ -858,7 +2041,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -873,20 +2056,54 @@ dependencies = [ [[package]] name = "tilejson" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a16212e5ea60f2b406835981338a1df9b206fab312e3470502d60f69e590a9c9" +checksum = "860f93502e95360a4f3989076db613dd8c428798c90b3d8bf07b51cd8916ac0d" dependencies = [ "serde", "serde_json", "serde_tuple", + "thiserror", ] +[[package]] +name = "time" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +dependencies = [ + "deranged", + "powerfmt", + "serde", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" -version = "1.33.0" +version = "1.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" dependencies = [ "backtrace", "bytes", @@ -898,18 +2115,29 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", +] + +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", ] [[package]] @@ -918,6 +2146,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -931,7 +2160,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -946,21 +2175,32 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.4" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ "log", "once_cell", "tracing-core", ] +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ + "chrono", "matchers", "nu-ansi-term", "once_cell", @@ -973,31 +2213,91 @@ dependencies = [ "tracing", "tracing-core", "tracing-log", + "tracing-serde", ] +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "unindent" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf8parse" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "utilejson" +version = "0.2.0" +dependencies = [ + "serde", + "serde_json", + "tilejson", + "utiles", +] + [[package]] name = "utiles" version = "0.2.0" dependencies = [ - "anyhow", "fast_hilbert", "geo-types", "geojson", @@ -1005,7 +2305,6 @@ dependencies = [ "serde_json", "thiserror", "tilejson", - "tracing", ] [[package]] @@ -1014,16 +2313,46 @@ version = "0.2.0" dependencies = [ "clap", "clap-verbosity-flag", + "futures", "globset", "ignore", "rusqlite", "serde", "serde_json", "thiserror", + "time", + "tokio", + "tokio-stream", + "tracing", + "tracing-subscriber", + "utilejson", + "utiles", + "utilesqlite", + "walkdir", +] + +[[package]] +name = "utiles-dev" +version = "0.2.0" +dependencies = [ + "anyhow", + "deadpool-sqlite", + "fast_hilbert", + "futures", + "geo-types", + "geojson", + "geozero", + "rusqlite", + "serde", + "serde_json", + "sqlx", + "thiserror", + "tilejson", "tokio", "tracing", "tracing-subscriber", "utiles", + "utiles-cli", "utilesqlite", ] @@ -1031,6 +2360,7 @@ dependencies = [ name = "utilesqlite" version = "0.2.0" dependencies = [ + "deadpool-sqlite", "rusqlite", "serde", "serde_json", @@ -1074,6 +2404,78 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.39", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "whoami" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" + [[package]] name = "winapi" version = "0.3.9" @@ -1105,13 +2507,31 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -1120,13 +2540,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -1135,58 +2570,118 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "wkt" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c2252781f8927974e8ba6a67c965a759a2b88ea2b1825f6862426bbb1c8f41" +dependencies = [ + "geo-types", + "log", + "num-traits", + "thiserror", +] + [[package]] name = "zerocopy" -version = "0.7.20" +version = "0.7.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd66a62464e3ffd4e37bd09950c2b9dd6c4f8767380fabba0d523f9a775bc85a" +checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.20" +version = "0.7.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "255c4596d41e6916ced49cfafea18727b24d67878fa180ddfd69b9df34fd1726" +checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/Cargo.toml b/Cargo.toml index 17850f99..1b7d13f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,8 @@ crate-type = ["cdylib"] fast_hilbert = "2.0.0" geo-types = "0.7.9" pyo3 = "0.20.0" -rusqlite = "0.29.0" +rusqlite.workspace = true + serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.96" utiles = { path = "crates/utiles" } @@ -42,8 +43,10 @@ pyo3-build-config.workspace = true resolver = "2" members = [ "crates/utiles", + "crates/utilejson", "crates/utilesqlite", - "crates/utiles-cli" + "crates/utiles-cli", + "crates/utiles-dev" ] [workspace.package] @@ -62,7 +65,7 @@ geo-types = "0.7.9" geojson = "0.24.1" pyo3 = "0.20.0" pyo3-build-config = "0.20.0" -rusqlite = { version = "0.29.0", features = ["bundled", "vtab", "blob"] } +rusqlite = { version = "^0.30.0", features = ["bundled", "vtab", "blob"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.96" thiserror = "1.0.50" diff --git a/bench/test_bench.py b/bench/test_bench.py index 0ed95ec7..3590321d 100644 --- a/bench/test_bench.py +++ b/bench/test_bench.py @@ -3,8 +3,8 @@ import mercantile import pytest +from pmtiles.tile import tileid_to_zxy, zxy_to_tileid from pytest_benchmark.fixture import BenchmarkFixture -from pmtiles.tile import zxy_to_tileid, tileid_to_zxy import utiles @@ -118,11 +118,11 @@ def test_tiles_gen_bench(func: Callable[[], None], benchmark: BenchmarkFixture) # COORDS BENCH ~ COORDS BENCH ~ COORDS BENCH ~ COORDS BENCH ~ COORDS BENCH # ======================================================================== def mercantile_coords(obj: Any) -> None: - assert list(mercantile._coords(obj)) == [(1, 2)] # noqa: S101 + assert list(mercantile._coords(obj)) == [(1, 2)] def utiles_coords(obj: Any) -> None: - assert list(utiles._coords(obj)) == [(1, 2)] # noqa: S101 + assert list(utiles._coords(obj)) == [(1, 2)] @pytest.mark.benchmark( diff --git a/bench/test_build_profile.py b/bench/test_build_profile.py index de1b9f40..beed895a 100644 --- a/bench/test_build_profile.py +++ b/bench/test_build_profile.py @@ -4,7 +4,7 @@ def test_check_build_profile() -> None: - assert ( # noqa: S101 + assert ( utiles.__build_profile__ == "debug" or utiles.__build_profile__ == "release" ), f"utiles.__build_profile__ is not 'debug'/'release': {utiles.__build_profile__}" if utiles.__build_profile__ == "debug": diff --git a/bench/test_eq.py b/bench/test_eq.py index dd95acec..5991dcc5 100644 --- a/bench/test_eq.py +++ b/bench/test_eq.py @@ -8,7 +8,7 @@ def test_tile_equality() -> None: t = (1, 2, 3) tile_obj = utiles.from_tuple(t) - assert tile_obj == t # noqa: S101 + assert tile_obj == t def _equal(a: Any, b: Any) -> bool: diff --git a/crates/utilejson/Cargo.toml b/crates/utilejson/Cargo.toml new file mode 100644 index 00000000..73203066 --- /dev/null +++ b/crates/utilejson/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "utilejson" +edition.workspace = true +version.workspace = true +homepage.workspace = true +documentation.workspace = true +repository.workspace = true +authors.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +tilejson.workspace = true +serde.workspace = true +serde_json.workspace = true +utiles = { path = "../utiles" } diff --git a/crates/utilejson/src/lib.rs b/crates/utilejson/src/lib.rs new file mode 100644 index 00000000..e4376885 --- /dev/null +++ b/crates/utilejson/src/lib.rs @@ -0,0 +1,17 @@ +use serde_json; +use tilejson::TileJSON; + +/// # Panics +/// +/// Panics from `serde_json::to_string_pretty` or `serde_json::to_string` +#[must_use] +pub fn tilejson_stringify(tj: &TileJSON, fmt: Option) -> String { + match fmt { + Some(false) => serde_json::to_string(&tj).unwrap(), + _ => serde_json::to_string_pretty(&tj).unwrap(), + } +} + +pub fn tilejson_parse(s: &str) -> Result { + serde_json::from_str(s) +} diff --git a/crates/utiles-cli/Cargo.lock b/crates/utiles-cli/Cargo.lock deleted file mode 100644 index e05967d5..00000000 --- a/crates/utiles-cli/Cargo.lock +++ /dev/null @@ -1,1119 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - -[[package]] -name = "anstream" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" - -[[package]] -name = "anstyle-parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" -dependencies = [ - "anstyle", - "windows-sys", -] - -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" - -[[package]] -name = "bstr" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clap" -version = "4.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap-verbosity-flag" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5fdbb015d790cfb378aca82caf9cc52a38be96a7eecdb92f31b4366a8afc019" -dependencies = [ - "clap", - "log", -] - -[[package]] -name = "clap_builder" -version = "4.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "clap_lex" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" - -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "fallible-iterator" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" - -[[package]] -name = "fallible-streaming-iterator" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" - -[[package]] -name = "fast_hilbert" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ec2bbe15af87954c739e236021f4411766c0f2b9c4a5f0b9317bcf6048ebf8" -dependencies = [ - "num-traits", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "geo-types" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9705398c5c7b26132e74513f4ee7c1d7dafd786004991b375c172be2be0eecaa" -dependencies = [ - "approx", - "num-traits", - "serde", -] - -[[package]] -name = "geojson" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d728c1df1fbf328d74151efe6cb0586f79ee813346ea981add69bd22c9241b" -dependencies = [ - "geo-types", - "log", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "gimli" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" - -[[package]] -name = "globset" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" -dependencies = [ - "aho-corasick", - "bstr", - "fnv", - "log", - "regex", -] - -[[package]] -name = "hashbrown" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" -dependencies = [ - "ahash", - "allocator-api2", -] - -[[package]] -name = "hashlink" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" -dependencies = [ - "hashbrown", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - -[[package]] -name = "ignore" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" -dependencies = [ - "globset", - "lazy_static", - "log", - "memchr", - "regex", - "same-file", - "thread_local", - "walkdir", - "winapi-util", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.149" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "libsqlite3-sys" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - -[[package]] -name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" -dependencies = [ - "libc", - "wasi", - "windows-sys", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "proc-macro2" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "regex" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.3", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "rusqlite" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" -dependencies = [ - "bitflags 2.4.1", - "fallible-iterator", - "fallible-streaming-iterator", - "hashlink", - "libsqlite3-sys", - "smallvec", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "serde" -version = "1.0.190" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.190" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "serde_json" -version = "1.0.108" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_tuple" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f025b91216f15a2a32aa39669329a475733590a015835d1783549a56d09427" -dependencies = [ - "serde", - "serde_tuple_macros", -] - -[[package]] -name = "serde_tuple_macros" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4076151d1a2b688e25aaf236997933c66e18b870d0369f8b248b8ab2be630d7e" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "smallvec" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" - -[[package]] -name = "socket2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "thread_local" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "tilejson" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a16212e5ea60f2b406835981338a1df9b206fab312e3470502d60f69e590a9c9" -dependencies = [ - "serde", - "serde_json", - "serde_tuple", -] - -[[package]] -name = "tokio" -version = "1.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys", -] - -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "tokio-rusqlite" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aa66395f5ff117faee90c9458232c936405f9227ad902038000b74b3bc1feac" -dependencies = [ - "crossbeam-channel", - "rusqlite", - "tokio", -] - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "serde", - "serde_json", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "utiles" -version = "0.0.1" -dependencies = [ - "anyhow", - "fast_hilbert", - "geo-types", - "geojson", - "serde", - "serde_json", - "thiserror", - "tilejson", - "tracing", -] - -[[package]] -name = "utiles-cli" -version = "0.0.1" -dependencies = [ - "clap", - "clap-verbosity-flag", - "globset", - "ignore", - "rusqlite", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", - "tracing-subscriber", - "utiles", - "utilesqlite", -] - -[[package]] -name = "utilesqlite" -version = "0.1.0" -dependencies = [ - "rusqlite", - "serde", - "serde_json", - "tilejson", - "tokio", - "tokio-rusqlite", - "tracing", - "utiles", -] - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "walkdir" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "zerocopy" -version = "0.7.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686b7e407015242119c33dab17b8f61ba6843534de936d94368856528eae4dcc" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020f3dfe25dfc38dfea49ce62d5d45ecdd7f0d8a724fa63eb36b6eba4ec76806" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] diff --git a/crates/utiles-cli/Cargo.toml b/crates/utiles-cli/Cargo.toml index 8e24429b..819b82d1 100644 --- a/crates/utiles-cli/Cargo.toml +++ b/crates/utiles-cli/Cargo.toml @@ -14,16 +14,21 @@ name = "ut" path = "src/bin.rs" [dependencies] -rusqlite.workspace = true -tokio.workspace = true +rusqlite = { workspace=true, features = ["bundled", "hooks"] } +tokio = { workspace = true, features = ["fs"] } tracing.workspace = true -tracing-subscriber.workspace = true +tracing-subscriber= {workspace= true, features = ["fmt", "json", "env-filter", "chrono"]} serde.workspace = true serde_json.workspace = true thiserror.workspace= true -clap = { version = "4.4.7", features = ["derive"] } +clap = { version = "4.4.7", features = ["derive", "color"] } clap-verbosity-flag = "2.1.0" globset = "0.4.13" ignore = "0.4.20" utiles = { path = "../utiles" } +utilejson = { path = "../utilejson" } utilesqlite = { path = "../utilesqlite" } +tokio-stream = "0.1.14" +futures = "0.3.29" +walkdir = "2.4.0" +time = "0.3.30" diff --git a/crates/utiles-cli/src/args.rs b/crates/utiles-cli/src/args.rs index 7963067d..9e21fa48 100644 --- a/crates/utiles-cli/src/args.rs +++ b/crates/utiles-cli/src/args.rs @@ -1,73 +1,121 @@ -use crate::shapes::ShapesArgs; use clap::{Parser, Subcommand}; use utiles::LngLat; -/// A fictional versioning CLI +use crate::commands::dev::DevArgs; +use utiles::VERSION; + +use crate::commands::shapes::ShapesArgs; + +fn about() -> String { + format!("utiles cli (rust) ~ v{VERSION}") +} + #[derive(Debug, Parser)] // requires `derive` feature -#[command(name = "ut")] -#[command(about = "utiles cli (rust)", long_about = None)] +#[command(name = "ut", about = about(), version = VERSION, long_about = None, author)] pub struct Cli { + /// debug mode (print/log a lot of stuff) + #[arg(long, short, global = true, default_value = "false", help = "debug mode", action = clap::ArgAction::SetTrue)] + pub debug: bool, + #[command(subcommand)] pub command: Commands, - - // debug flag - #[arg( - long, - short, - global = true, - default_value = "false", - help = "debug mode" - )] - pub debug: bool, - // #[command(flatten , help="verbosity level (-v, -vv, -vvv, -vvvv)" )] - // verbose: Verbosity, } #[derive(Debug, Parser)] // requires `derive` feature -pub struct InputAndSequenceArgs { - /// The remote to clone +pub struct TileInputStreamArgs { #[arg(required = false)] - input: Option, + pub input: Option, +} +#[derive(Debug, Parser)] // requires `derive` feature +pub struct TileFmtOptions { #[arg(required = false, long, action = clap::ArgAction::SetTrue)] - seq: bool, + pub seq: bool, + + #[arg(required = false, long, action = clap::ArgAction::SetTrue)] + pub obj: bool, } #[derive(Debug, Parser)] // requires `derive` feature pub struct TilesArgs { - /// The remote to clone #[arg(required = true)] pub zoom: u8, - // #[command(flatten)] - // pub shared: InputAndSequenceArgs, - #[arg(required = false)] - pub input: Option, + #[command(flatten)] + pub inargs: TileInputStreamArgs, - #[arg(required = false, long, action = clap::ArgAction::SetTrue)] - pub seq: bool, + #[command(flatten)] + pub fmtopts: TileFmtOptions, +} + +#[derive(Debug, Parser)] // requires `derive` feature +pub struct TileFmtArgs { + #[command(flatten)] + pub inargs: TileInputStreamArgs, + + #[command(flatten)] + pub fmtopts: TileFmtOptions, +} + +#[derive(Debug, Parser)] +pub struct ParentChildrenArgs { + #[command(flatten)] + pub inargs: TileInputStreamArgs, + + #[command(flatten)] + pub fmtopts: TileFmtOptions, + + #[arg(required = false, long, default_value = "1")] + pub depth: u8, +} + +#[derive(Debug, Parser)] // requires `derive` feature +pub struct SqliteDbCommonArgs { + #[arg(required = true, help = "mbtiles filepath")] + pub filepath: String, + + #[arg(required = false, short, long, help = "compact json", action = clap::ArgAction::SetTrue)] + pub min: bool, +} + +#[derive(Debug, Parser)] // requires `derive` feature +pub struct TilejsonArgs { + #[command(flatten)] + pub common: SqliteDbCommonArgs, + + #[arg(required = false, short, long, help = "include tilestats", action = clap::ArgAction::SetTrue)] + pub tilestats: bool, +} + +#[derive(Debug, Parser)] // requires `derive` feature +pub struct LintArgs { + #[arg(required = true, help = "filepath(s) or dirpath(s)", num_args(1..))] + pub(crate) fspaths: Vec, + + #[arg(required = false, long, action = clap::ArgAction::SetTrue, default_value = "false")] + pub(crate) fix: bool, } #[derive(Debug, Subcommand)] pub enum Commands { + #[command(name = "tilejson", visible_alias = "tj", alias = "trader-joes", about = "Echo tilejson for mbtiles file(s)", long_about = None)] + Tilejson(TilejsonArgs), + + #[command(name = "copy", about = "Copy tiles from src -> dst", long_about = None, visible_alias = "cp")] + Copy(CopyArgs), + #[command(name = "lint", about = "Lint mbtiles file(s)", long_about = None)] - Lint { - #[arg(required = true, help = "filepath(s) or dirpath(s)", num_args(1..))] - fspaths: Vec, + Lint(LintArgs), - #[arg(required = false, long, action = clap::ArgAction::SetTrue)] - fix: bool, - }, - #[command(name = "tilejson", visible_alias = "tj", about = "Echo tileson for mbtiles file(s)", long_about = None)] - Tilejson { - #[arg(required = true, help = "mbtiles filepath")] - filepath: String, + /// metadata - #[arg(required = false, short, long, help = "compact json", action = clap::ArgAction::SetTrue)] - min: bool, - }, + #[command(name = "metadata", visible_alias = "md", about = "Echo metadata (table) as json", long_about = None)] + Meta(SqliteDbCommonArgs), - #[command(name = "contains", about = "Determine if mbtiles contains a latlong", long_about = None)] + #[command(name = "rimraf", about = "rm-rf dirpath", long_about = None, visible_alias = "rmrf")] + Rimraf(RimrafArgs), + + #[command(name = "dbcontains", about = "Determine if mbtiles contains a latlong", long_about = None)] Contains { #[arg(required = true, help = "mbtiles filepath")] filepath: String, @@ -76,84 +124,61 @@ pub enum Commands { lnglat: LngLat, }, - #[command(name = "metadata", visible_alias = "md", about = "Echo metadata (table) as json", long_about = None)] - Meta { - #[arg(required = true, help = "mbtiles filepath")] - filepath: String, - - #[arg(required = false, short, long, help = "compact json", action = clap::ArgAction::SetTrue)] - min: bool, - // #[arg(required = false, short, long, help= "compact json", action = clap::ArgAction::SetTrue)] - // raw: bool, - }, - // ======================================================================== // TILE CLI UTILS - MERCANTILE LIKE CLI // ======================================================================== + #[command(name = "bounding-tile", about = "Echo the bounding tile of a lonlat/bbox/GeoJSON", long_about = None)] + BoundingTile(TileFmtArgs), + + #[command(name = "quadkey", visible_alias = "qk", about = "Convert to/from quadkey(s)", long_about = None)] + Quadkey(TileFmtArgs), + #[command(name = "tiles", about = "Echo tiles of bbox", long_about = None)] Tiles(TilesArgs), - // { - // #[arg(required = true)] - // zoom: u8, - // - // #[arg(required = false)] - // input: Option, - // - // #[arg(required = false, long, action = clap::ArgAction::SetTrue)] - // seq: bool, - // }, - #[command(name = "quadkey", visible_alias = "qk", about = "Convert to/from quadkey(s)", long_about = None)] - Quadkey { - #[arg(required = false)] - input: Option, - }, #[command(name = "pmtileid", visible_alias = "pmid", about = "Convert to/from pmtile id(s)", long_about = None)] - PMTileID { - #[arg(required = false)] - input: Option, - }, + Pmtileid(TileFmtArgs), - #[command(name = "bounding-tile", about = "Echo the bounding tile of a lonlat/bbox/GeoJSON", long_about = None)] - BoundingTile { - #[arg(required = false)] - input: Option, - - #[arg(required = false, long, action = clap::ArgAction::SetTrue)] - seq: bool, - }, #[command(name = "neighbors", about = "Echo neighbors of tile(s)", long_about = None)] - Neighbors { - #[arg(required = false)] - input: Option, + Neighbors(TileFmtArgs), - #[arg(required = false, long, action = clap::ArgAction::SetTrue)] - seq: bool, - }, + #[command(name = "children", about = "Echo children of tile(s)", long_about = None)] + Children(ParentChildrenArgs), #[command(name = "parent", about = "Echo parent of tile(s)", long_about = None)] - Parent { - #[arg(required = false)] - input: Option, + Parent(ParentChildrenArgs), - #[arg(required = false, long, action = clap::ArgAction::SetTrue)] - seq: bool, + #[command(name = "shapes", about = "Echo shapes of tile(s) as GeoJSON", long_about = None)] + Shapes(ShapesArgs), - #[arg(required = false, long, default_value = "1")] - depth: u8, - }, - #[command(name = "children", about = "Echo children of tile(s)", long_about = None)] - Children { - #[arg(required = false)] - input: Option, + /// Development/Playground command (hidden) + #[command(name = "dev", about = "dev command", long_about = None, hide = true, hide = true)] + Dev(DevArgs), +} - #[arg(required = false, long, action = clap::ArgAction::SetTrue)] - seq: bool, +#[derive(Debug, Parser, Clone)] // requires `derive` feature +#[command(name = "rimraf", about = "rm-rf dirpath", long_about = None)] +pub struct RimrafArgs { + #[arg(required = true, help = "dirpath to rm")] + pub dirpath: String, - #[arg(required = false, long, default_value = "1")] - depth: u8, - }, + #[arg(required = false, long, action = clap::ArgAction::SetTrue)] + pub(crate) size: bool, - #[command(name = "shapes", about = "Echo shapes of tile(s) as GeoJSON", long_about = None)] - Shapes(ShapesArgs), + #[arg(required = false, long, action = clap::ArgAction::SetTrue)] + verbose: bool, +} + +#[derive(Debug, Parser)] // requires `derive` feature +#[command(name = "copy", about = "Copy tiles from src -> dst", long_about = None)] +pub struct CopyArgs { + #[arg(required = true, help = "src dataset fspath")] + pub src: String, + + #[arg(required = true, help = "dst dataset fspath")] + pub dst: String, + + /// force overwrite dst + #[arg(required = false, long, short, action = clap::ArgAction::SetTrue)] + pub force: bool, } diff --git a/crates/utiles-cli/src/bin.rs b/crates/utiles-cli/src/bin.rs index 2fb3ecfa..e8a62c9d 100644 --- a/crates/utiles-cli/src/bin.rs +++ b/crates/utiles-cli/src/bin.rs @@ -1,8 +1,7 @@ mod args; mod cli; mod commands; -mod lint; -mod shapes; +mod find; mod stdinterator; mod stdinterator_filter; diff --git a/crates/utiles-cli/src/cli.rs b/crates/utiles-cli/src/cli.rs index b096658a..d3fec81b 100644 --- a/crates/utiles-cli/src/cli.rs +++ b/crates/utiles-cli/src/cli.rs @@ -1,20 +1,39 @@ use std::io::{self}; -use std::path::Path; -use crate::args::{Cli, Commands}; -use crate::commands::tiles::tiles_main; -use crate::lint::lint_main; -use crate::shapes::shapes_main; -use crate::stdinterator_filter; use clap::Parser; -use tracing::{debug, error, warn}; +use tracing::{debug, warn}; +use tracing_subscriber::fmt::{self}; use tracing_subscriber::EnvFilter; -use utiles::mbtiles::metadata_row::MbtilesMetadataRow; -use utiles::parsing::parse_bbox; -use utiles::tilejson::tilejson_stringify; -use utiles::{bounding_tile, Tile}; -use utilesqlite::mbtiles::Mbtiles; -// #[group(ArgGroup::new("projected").args(&["geographic", "mercator"]).required(false))] + +use crate::args::{Cli, Commands}; +use crate::commands::copy::copy_main; +use crate::commands::dev::dev_main; +use crate::commands::lint::lint_main; +use crate::commands::rimraf::rimraf_main; +use crate::commands::shapes::shapes_main; +use crate::commands::tiles::tiles_main; +use crate::commands::{ + bounding_tile_main, contains_main, metadata_main, neighbors_main, pmtileid_main, + quadkey_main, tilejson_main, +}; +use crate::commands::{children_main, parent_main}; + +fn init_tracing(debug: bool) { + let filter = if debug { + EnvFilter::new("DEBUG") + } else { + EnvFilter::new("INFO") + }; + let subscriber = fmt::Subscriber::builder() + .compact() + .with_target(true) + .with_line_number(false) + .with_env_filter(filter) + .with_writer(io::stderr) + .finish(); + tracing::subscriber::set_global_default(subscriber) + .expect("tracing::subscriber::set_global_default(...) failed."); +} #[allow(clippy::unused_async)] pub async fn cli_main(argv: Option>, loop_fn: Option<&dyn Fn()>) -> u8 { @@ -24,208 +43,46 @@ pub async fn cli_main(argv: Option>, loop_fn: Option<&dyn Fn()>) -> None => std::env::args().collect::>(), }; let args = Cli::parse_from(&argv); - let filter = if args.debug { - EnvFilter::new("DEBUG") + + // if the command is "dev" init tracing w/ debug + if let Commands::Dev(_) = args.command { + init_tracing(true); } else { - EnvFilter::new("WARN") - }; - // Install the global collector configured based on the filter. - tracing_subscriber::fmt() - .with_env_filter(filter) - .with_writer(io::stderr) - .init(); + init_tracing(args.debug); + } debug!("args: {:?}", std::env::args().collect::>()); debug!("argv: {:?}", argv); - debug!("args: {:?}", args); match args.command { - Commands::Lint { - fspaths: filepath, - fix, - } => { - if fix { + Commands::Lint(args) => { + if args.fix { warn!("fix not implemented"); } - lint_main(&filepath, fix); + lint_main(&args); } - Commands::Meta { filepath, min } => { - debug!("meta: {filepath}"); - // check that filepath exists and is file - let filepath = Path::new(&filepath); - assert!( - filepath.exists(), - "File does not exist: {}", - filepath.display() - ); - assert!( - filepath.is_file(), - "Not a file: {filepath}", - filepath = filepath.display() - ); - let mbtiles: Mbtiles = Mbtiles::from(filepath); - // let mbtiles = Mbtiles::from_filepath(&filepath).unwrap(); - let metadata_rows = mbtiles.metadata().unwrap(); - if min { - let s = - serde_json::to_string::>(&metadata_rows) - .unwrap(); - println!("{s}"); - } else { - let s = serde_json::to_string_pretty::>( - &metadata_rows, - ) - .unwrap(); - println!("{s}"); - } + Commands::Meta(args) => metadata_main(&args), + Commands::Tilejson(args) => tilejson_main(&args), + Commands::Copy(args) => { + // copy_main(args); + copy_main(args).await; } - - Commands::Tilejson { filepath, min } => { - debug!("tilejson: {filepath}"); - // check that filepath exists and is file - let filepath = Path::new(&filepath); - assert!( - filepath.exists(), - "File does not exist: {}", - filepath.display() - ); - assert!( - filepath.is_file(), - "Not a file: {filepath}", - filepath = filepath.display() - ); - let mbtiles: Mbtiles = Mbtiles::from(filepath); - // let mbtiles = Mbtiles::from_filepath(&filepath).unwrap(); - let tj = mbtiles.tilejson().unwrap(); - let s = tilejson_stringify(&tj, Option::from(!min)); - println!("{s}"); + Commands::Dev(args) => { + let _r = dev_main(args).await; } - - Commands::Contains { filepath, lnglat } => { - debug!("contains: {filepath}"); - // check that filepath exists and is file - let filepath = Path::new(&filepath); - assert!( - filepath.exists(), - "File does not exist: {}", - filepath.display() - ); - assert!( - filepath.is_file(), - "Not a file: {filepath}", - filepath = filepath.display() - ); - let mbtiles: Mbtiles = Mbtiles::from(filepath); - let contains = mbtiles.contains(lnglat); - if contains.is_err() { - error!("contains error: {:?}", contains); - println!("contains error: {:?}", contains); - } else { - println!("{}", contains.unwrap()); - } + Commands::Rimraf(args) => { + rimraf_main(args).await; } - + Commands::Contains { filepath, lnglat } => contains_main(&filepath, lnglat), // mercantile cli like - Commands::Quadkey { input } => { - let lines = stdinterator_filter::stdin_filtered(input); - for line in lines { - // if the line bgins w '[' treat as tile - // otherwise treat as quadkey - let lstr = line.unwrap(); - if lstr.starts_with('[') { - // treat as tile - let tile = Tile::from_json_arr(&lstr); - println!("{}", tile.quadkey()); - } else { - // treat as quadkey - let qk = lstr; - let tile = Tile::from_quadkey(&qk); - if tile.is_err() { - error!("Invalid quadkey: {qk}"); - println!("Invalid quadkey: {qk}"); - } else { - println!("{}", tile.unwrap().json_arr()); - } - } - } - } - - // Convert between tile id (xyz) and pmtileid - Commands::PMTileID { input } => { - let lines = stdinterator_filter::stdin_filtered(input); - for line in lines { - // if the line bgins w '[' treat as tile - let lstr = line.unwrap(); - if lstr.starts_with('[') { - // treat as tile - let tile = Tile::from_json_arr(&lstr); - println!("{}", tile.pmtileid()); - } else { - // treat as pmtileid - let pmid: u64 = lstr.parse().unwrap(); - let tile = Tile::from_pmid(pmid); - if tile.is_err() { - error!("Invalid pmtileid: {pmid}"); - println!("Invalid pmtileid: {pmid}"); - } else { - println!("{}", tile.unwrap().json_arr()); - } - } - } - } - - Commands::BoundingTile { input, seq } => { - let lines = stdinterator_filter::stdin_filtered(input); - let bboxes = lines.map(|l| { - let s = l.unwrap(); - debug!("l: {:?}", s); - parse_bbox(&s).unwrap() - }); - for bbox in bboxes { - let tile = bounding_tile(bbox, None); - // let tile = Tile::from_bbox(&bbox, zoom); - let rs = if seq { "\x1e\n" } else { "" }; - println!("{}{}", rs, tile.json_arr()); - } - } + Commands::Quadkey(args) => quadkey_main(args), + Commands::Pmtileid(args) => pmtileid_main(args), + Commands::BoundingTile(args) => bounding_tile_main(args), Commands::Tiles(args) => tiles_main(args, loop_fn), - Commands::Neighbors { input, seq } => { - let lines = stdinterator_filter::stdin_filtered(input); - let tiles = lines.map(|l| Tile::from_json(&l.unwrap())); - for tile in tiles { - let neighbors = tile.neighbors(); - for neighbor in neighbors { - let rs = if seq { "\x1e\n" } else { "" }; - println!("{}{}", rs, neighbor.json_arr()); - } - } - } - - Commands::Children { input, seq, depth } => { - let lines = stdinterator_filter::stdin_filtered(input); - let tiles = lines.map(|l| Tile::from_json(&l.unwrap())); - for tile in tiles { - let children = tile.children(Option::from(tile.z + depth)); - for child in children { - let rs = if seq { "\x1e\n" } else { "" }; - println!("{}{}", rs, child.json_arr()); - } - } - } - - Commands::Parent { input, seq, depth } => { - let lines = stdinterator_filter::stdin_filtered(input); - let tiles = lines.map(|l| Tile::from_json(&l.unwrap())); - for tile in tiles { - let nup = i32::from(tile.z) - i32::from(depth); - // error - assert!(nup >= 0, "depth must be less than or equal to tile zoom"); - let parent = tile.parent(Option::from(depth - 1)); - let rs = if seq { "\x1e\n" } else { "" }; - println!("{}{}", rs, parent.json_arr()); - } - } + Commands::Neighbors(args) => neighbors_main(args), + Commands::Children(args) => children_main(args), + Commands::Parent(args) => parent_main(args), Commands::Shapes(args) => { shapes_main(args); } @@ -244,3 +101,14 @@ pub fn cli_main_sync(argv: Option>, loop_fn: Option<&dyn Fn()>) -> u .block_on(async { cli_main(argv, loop_fn).await }); r } + +#[cfg(test)] +mod tests { + use crate::args::Cli; + + #[test] + fn verify_cli() { + use clap::CommandFactory; + Cli::command().debug_assert(); + } +} diff --git a/crates/utiles-cli/src/commands/children_parent.rs b/crates/utiles-cli/src/commands/children_parent.rs new file mode 100644 index 00000000..8a806b67 --- /dev/null +++ b/crates/utiles-cli/src/commands/children_parent.rs @@ -0,0 +1,29 @@ +use utiles::{Tile, TileLike}; + +use crate::args::ParentChildrenArgs; +use crate::stdinterator_filter; + +pub fn parent_main(args: ParentChildrenArgs) { + let lines = stdinterator_filter::stdin_filtered(args.inargs.input); + let tiles = lines.map(|l| Tile::from_json(&l.unwrap())); + for tile in tiles { + let nup = i32::from(tile.z) - i32::from(args.depth); + // error + assert!(nup >= 0, "depth must be less than or equal to tile zoom"); + let parent = tile.parent(Option::from(args.depth - 1)); + let rs = if args.fmtopts.seq { "\x1e\n" } else { "" }; + println!("{}{}", rs, parent.json_arr()); + } +} + +pub fn children_main(args: ParentChildrenArgs) { + let lines = stdinterator_filter::stdin_filtered(args.inargs.input); + let tiles = lines.map(|l| Tile::from_json(&l.unwrap())); + for tile in tiles { + let children = tile.children(Option::from(tile.z + args.depth)); + for child in children { + let rs = if args.fmtopts.seq { "\x1e\n" } else { "" }; + println!("{}{}", rs, child.json_arr()); + } + } +} diff --git a/crates/utiles-cli/src/commands/contains.rs b/crates/utiles-cli/src/commands/contains.rs new file mode 100644 index 00000000..7c1fc2ce --- /dev/null +++ b/crates/utiles-cli/src/commands/contains.rs @@ -0,0 +1,32 @@ +use std::path::Path; +use tracing::{debug, error}; + +use utiles::LngLat; +use utilesqlite::Mbtiles; + +/// Check if an mbtiles file contains a lnglat +/// +/// Added by [dan-costello](https://github.com/dan-costello) +pub fn contains_main(filepath: &str, lnglat: LngLat) { + debug!("contains: {filepath}"); + // check that filepath exists and is file + let filepath = Path::new(filepath); + assert!( + filepath.exists(), + "File does not exist: {}", + filepath.display() + ); + assert!( + filepath.is_file(), + "Not a file: {filepath}", + filepath = filepath.display() + ); + let mbtiles: Mbtiles = Mbtiles::from(filepath); + let contains = mbtiles.contains(lnglat); + if contains.is_err() { + error!("contains error: {:?}", contains); + println!("contains error: {contains:?}"); + } else { + println!("{}", contains.unwrap()); + } +} diff --git a/crates/utiles-cli/src/commands/copy.rs b/crates/utiles-cli/src/commands/copy.rs new file mode 100644 index 00000000..f5f31d71 --- /dev/null +++ b/crates/utiles-cli/src/commands/copy.rs @@ -0,0 +1,249 @@ +use std::cell::Cell; +use std::path::{Path, PathBuf}; + +// use tokio_stream::{self as stream, Stream}; +use crate::args::CopyArgs; +use futures::stream::{self, StreamExt}; +use serde_json; +use tokio::fs; +use tracing::{debug, info, warn}; +use utiles::mbtiles::MbtTileRow; +use utiles::{flipy, Tile, TileLike}; +use utilesqlite::Mbtiles; + +// #[derive(Debug)] +// pub struct MbtTileRow { +// zoom_level: u8, +// tile_column: u32, +// tile_row: u32, +// tile_data: Vec, +// } +// +#[derive(Debug)] +pub struct WriterStats { + pub nwritten: Cell, +} + +#[derive(Debug)] +struct TilesFsWriter { + root_dirpath: String, + stats: WriterStats, +} + +impl TilesFsWriter { + pub fn new(root_dirpath: String) -> Self { + Self { + root_dirpath, + stats: WriterStats { + nwritten: Cell::new(0), + }, + } + } + + fn dirpath(&self, z: u8, x: u32) -> PathBuf { + Path::new(&self.root_dirpath) + .join(format!("{z}")) + .join(format!("{x}")) + } + + pub async fn mkdirpath(&self, z: u8, x: u32) { + let dp = self.dirpath(z, x); + let dp = dp.to_str().unwrap(); + fs::create_dir_all(dp).await.unwrap(); + } + + pub async fn write_tile(&self, tile: MbtTileRow) { + let filepath = self.dirpath(tile.z(), tile.x()).join(format!( + "{}.{}", + flipy(tile.y(), tile.z()), + tile.extension() + )); + debug!("filepath: {:?}", filepath); + fs::write(filepath, tile.tile_data).await.unwrap(); + self.inc_nwritten(); + } + + pub fn inc_nwritten(&self) { + let n = self.stats.nwritten.get(); + self.stats.nwritten.set(n + 1); + } + + // pub fn nwritten(&self) -> u32 { + // self.stats.nwritten.get() + // } +} + +pub enum Source { + Mbtiles(String), +} + +pub enum Destination { + // Mbtiles(String), + Fs(String), +} + +async fn copy_mbtiles2fs(mbtiles: String, output_dir: String) { + let mbt = Mbtiles::from(mbtiles.as_ref()); + let start_time = std::time::Instant::now(); + let total_tiles: u32 = mbt + .conn() + .query_row("SELECT count(*) FROM tiles", [], |row| row.get(0)) + .unwrap(); + info!("finna write {total_tiles:?} from {mbtiles:?} to {output_dir:?}"); + let c = mbt.conn(); + + let metadata_vec = mbt.metadata().unwrap(); + let metadata_str = serde_json::to_string_pretty(&metadata_vec).unwrap(); + println!("{metadata_str}"); + // ensure output_dir exists + fs::create_dir_all(&output_dir).await.unwrap(); + // write metadata-json to output_dir/metadata.json + let metadata_path = Path::new(&output_dir).join("metadata.json"); + fs::write(metadata_path, metadata_str).await.unwrap(); + debug!("wrote metadata.json to {:?}", output_dir); + + let mut stmt_zx_distinct = c + .prepare("SELECT DISTINCT zoom_level, tile_column FROM tiles") + .unwrap(); + + let zx_iter = stmt_zx_distinct + .query_map([], |row| { + let zoom_level: u8 = row.get(0)?; + let tile_column: u32 = row.get(1)?; + let r = (zoom_level, tile_column); + Ok(r) + }) + .unwrap(); + + let twriter = TilesFsWriter::new(output_dir.to_string()); + + let zx_stream = stream::iter(zx_iter); + + zx_stream + .for_each_concurrent(10, |zx| async { + let zx = zx.unwrap(); + let z = zx.0; + let x = zx.1; + twriter.mkdirpath(z, x).await; + }) + .await; + + let mut stmt = c + .prepare("SELECT zoom_level, tile_column, tile_row, tile_data FROM tiles") + .unwrap(); + + let tiles_iter = stmt + .query_map([], |row| { + let zoom_level: u8 = row.get(0)?; + let tile_column: u32 = row.get(1)?; + + let tile_row: u32 = row.get(2)?; + let tile_data: Vec = row.get(3)?; + + let r = MbtTileRow::new(zoom_level, tile_column, tile_row, tile_data); + Ok(r) + }) + .unwrap(); + + let tiles_stream = stream::iter(tiles_iter); + + // let count = 0; + tiles_stream + .for_each_concurrent(0, |tile| async { + // print smaller rep + // println!("tile: {} {} {} {}" + // , tile.tile_column, tile.tile_row, tile.zoom_level, tile.tile_data.len()); + // sleep for .1 seconds + match tile { + Ok(tile) => { + let t = Tile::new(tile.tile_column, tile.tile_row, tile.zoom_level); + twriter.write_tile(tile).await; + debug!("Wrote tile: {}", t); + + // let dur2 = Duration::from_millis(1000); + // time::sleep(dur2).await; + } + Err(e) => { + println!("tile error: {e:?}"); + warn!("tile error: {:?}", e); + } + } + // let tile_msg = tile.json_obj(); + // let dur = Duration::from_millis(100); + + // time::sleep(dur).await; + // twriter.write_tile(tile).await; + // + // if twriter.nwritten() % 1000 == 0 { + // println!("nwritten: {:?}", twriter.nwritten()); + // let percent = (twriter.nwritten() as f32 / total_tiles as f32) * 100.0; + // // "nwritten: {:?} [{:?}]" + // let msg = format!("nwritten: {:?} [{:?}]", twriter.nwritten(), percent); + // // println!("percent: {:?}", percent); + // println!("{}", msg); + // } + + // sleep for .1 seconds + // let dur = Duration::from_millis(100); + // time::sleep(dur).await; + // println!("DONE tile: {:?}", tile_msg); + }) + .await; + + let end_time = std::time::Instant::now(); + let elapsed = end_time - start_time; + let elapsed_secs = elapsed.as_secs(); + println!("elapsed_secs: {elapsed_secs:?}"); +} + +pub struct CopyConfig { + pub src: Source, + pub dst: Destination, +} + +impl CopyConfig { + pub fn new(src: Source, dst: Destination) -> Self { + Self { src, dst } + } +} + +pub async fn copy_main(args: CopyArgs) { + warn!("experimental command: copy/cp"); + + //let file = "D:\\utiles\\blue-marble\\blue-marble.z0z4.normal.mbtiles"; + // make sure input file exists and is file... + let src_path = Path::new(&args.src); + assert!( + src_path.exists(), + "File does not exist: {}", + src_path.display() + ); + assert!( + src_path.is_file(), + "Not a file: {filepath}", + filepath = src_path.display() + ); + + // make sure output dir does not exist + let dst_path = Path::new(&args.dst); + let dst_path_exists = dst_path.exists(); + if dst_path_exists { + if args.force { + warn!("dst_path exists: {:?}, but force is true", dst_path); + } else { + assert!(!dst_path_exists, "File exists: {}", dst_path.display()); + } + } + let src = Source::Mbtiles(src_path.to_str().unwrap().to_string()); + let dst = Destination::Fs(dst_path.to_str().unwrap().to_string()); + + let cfg = CopyConfig::new(src, dst); + + match cfg.src { + Source::Mbtiles(filepath) => match cfg.dst { + Destination::Fs(output_dir) => { + copy_mbtiles2fs(filepath, output_dir).await; + } + }, + } +} diff --git a/crates/utiles-cli/src/commands/dev.rs b/crates/utiles-cli/src/commands/dev.rs new file mode 100644 index 00000000..eb9d3232 --- /dev/null +++ b/crates/utiles-cli/src/commands/dev.rs @@ -0,0 +1,28 @@ +use clap::Parser; +use tracing::{debug, warn}; + +/// ██╗ ██╗████████╗██╗██╗ ███████╗███████╗ ██████╗ ███████╗██╗ ██╗ +/// ██║ ██║╚══██╔══╝██║██║ ██╔════╝██╔════╝ ██╔══██╗██╔════╝██║ ██║ +/// ██║ ██║ ██║ ██║██║ █████╗ ███████╗█████╗██║ ██║█████╗ ██║ ██║ +/// ██║ ██║ ██║ ██║██║ ██╔══╝ ╚════██║╚════╝██║ ██║██╔══╝ ╚██╗ ██╔╝ +/// ╚██████╔╝ ██║ ██║███████╗███████╗███████║ ██████╔╝███████╗ ╚████╔╝ +/// ╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝ ╚═════╝ ╚══════╝ ╚═══╝ +#[derive(Debug, Parser)] +#[command(name = "dev", about = "dev", long_about = "development/playground")] +pub struct DevArgs { + #[arg(required = false)] + fspath: Option, +} +#[allow(clippy::unused_async)] +async fn dev(args: DevArgs) -> Result<(), Box> { + // DEV START + debug!("args: {:?}", args); + // DEV END + Ok(()) +} + +pub async fn dev_main(args: DevArgs) -> Result<(), Box> { + warn!("__DEV_MAIN__"); + dev(args).await?; + Ok(()) +} diff --git a/crates/utiles-cli/src/lint.rs b/crates/utiles-cli/src/commands/lint.rs similarity index 71% rename from crates/utiles-cli/src/lint.rs rename to crates/utiles-cli/src/commands/lint.rs index 0cb6da05..2fcd2910 100644 --- a/crates/utiles-cli/src/lint.rs +++ b/crates/utiles-cli/src/commands/lint.rs @@ -1,29 +1,19 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; -use globset::{Glob, GlobSetBuilder}; -use ignore::WalkBuilder; use tracing::{debug, info, warn}; use utiles::lint_error::{UtilesLintError, UtilesLintResult}; use utiles::mbtiles::{metadata2duplicates, metadata2map, MBTILES_MAGIC_NUMBER}; use utilesqlite::mbtiles::{is_mbtiles, Mbtiles}; +use crate::args::LintArgs; +use crate::find; use utilesqlite::squealite; pub const REQUIRED_METADATA_FIELDS: [&str; 7] = [ "name", "center", "bounds", "minzoom", "maxzoom", "format", "type", ]; -fn is_dir(path: &str) -> bool { - let path = std::path::Path::new(path); - path.is_dir() -} - -fn is_file(path: &str) -> bool { - let path = std::path::Path::new(path); - path.is_file() -} - pub fn lint_mbtiles_file(mbtiles: &Mbtiles, fix: bool) -> Vec { // println!("_________ lint_filepath _________"); // println!("lint (fix -- {fix})"); @@ -149,60 +139,12 @@ fn lint_filepaths(fspaths: Vec, fix: bool) { warn!("Error: {}", e); } } - // let r = lint_mbtiles_file(&path, fix); - // debug!("r: {:?}", r); - // // print each err.... - // if r.is_empty() { - // info!("No errors found"); - // } else { - // warn!("{} - {} errors found", path.display(), r.len()); - // - // // let agg_err = UtilesLintError::LintErrors(r); - // for err in r { - // warn!("{}", err.to_string()); - // } - // } - } -} - -pub fn find_filepaths(fspaths: &[String]) -> Vec { - let fspath = fspaths[0].clone(); - - let mut glob_builder = GlobSetBuilder::new(); - let glob = Glob::new("**/*.{mbtiles,sqlite,sqlite3}").unwrap(); - glob_builder.add(glob); - let globset = glob_builder.build().unwrap(); - - // filepaths - let mut filepaths: Vec = vec![]; - - if is_file(&fspath) { - filepaths.push(PathBuf::from(fspath)); - } else if is_dir(&fspath) { - let dirpath = PathBuf::from(fspath).canonicalize().unwrap(); - let walk_builder = WalkBuilder::new(dirpath); - for result in walk_builder.build().filter_map(std::result::Result::ok) { - if !result.file_type().unwrap().is_file() { - continue; - } - match result.path().to_str() { - Some(path) => { - if globset.is_match(path) { - filepaths.push(path.into()); - } - } - None => { - warn!("Unable to convert path to string: {:?}", result.path()); - } - } - } } - filepaths } -pub fn lint_main(fspaths: &[String], fix: bool) { - let filepaths = find_filepaths(fspaths); - if fix { +pub fn lint_main(args: &LintArgs) { + let filepaths = find::find_filepaths(&args.fspaths); + if args.fix { warn!("lint fix is not implemented yet"); } debug!("filepaths: {:?}", filepaths); @@ -210,7 +152,7 @@ pub fn lint_main(fspaths: &[String], fix: bool) { warn!("No files found"); return; } - lint_filepaths(filepaths, fix); + lint_filepaths(filepaths, args.fix); } pub fn lint_metadata_map(map: &HashMap) -> Vec { diff --git a/crates/utiles-cli/src/commands/metadb.rs b/crates/utiles-cli/src/commands/metadb.rs new file mode 100644 index 00000000..35510db9 --- /dev/null +++ b/crates/utiles-cli/src/commands/metadb.rs @@ -0,0 +1,36 @@ +use std::path::Path; + +use tracing::debug; + +use utiles::mbtiles::MbtilesMetadataRow; +use utilesqlite::Mbtiles; + +use crate::args::SqliteDbCommonArgs; + +pub fn metadata_main(args: &SqliteDbCommonArgs) { + debug!("meta: {}", args.filepath); + // check that filepath exists and is file + let filepath = Path::new(&args.filepath); + assert!( + filepath.exists(), + "File does not exist: {}", + filepath.display() + ); + assert!( + filepath.is_file(), + "Not a file: {filepath}", + filepath = filepath.display() + ); + let mbtiles: Mbtiles = Mbtiles::from(filepath); + // let mbtiles = Mbtiles::from_filepath(&filepath).unwrap(); + let metadata_rows = mbtiles.metadata().unwrap(); + if args.min { + let s = + serde_json::to_string::>(&metadata_rows).unwrap(); + println!("{s}"); + } else { + let s = serde_json::to_string_pretty::>(&metadata_rows) + .unwrap(); + println!("{s}"); + } +} diff --git a/crates/utiles-cli/src/commands/mod.rs b/crates/utiles-cli/src/commands/mod.rs index 627e8fcc..b36d071a 100644 --- a/crates/utiles-cli/src/commands/mod.rs +++ b/crates/utiles-cli/src/commands/mod.rs @@ -1 +1,25 @@ +pub use children_parent::{children_main, parent_main}; +pub use contains::contains_main; +pub use copy::copy_main; +pub use dev::dev_main; +pub use lint::lint_main; +pub use metadb::metadata_main; +pub use rimraf::rimraf_main; +pub use shapes::shapes_main; +pub use tile_stream_cmds::{ + bounding_tile_main, neighbors_main, pmtileid_main, quadkey_main, +}; +pub use tilejson::tilejson_main; +pub use tiles::tiles_main; + +mod children_parent; +mod contains; +pub mod copy; +pub mod dev; +pub mod lint; +mod metadb; +pub mod rimraf; +pub mod shapes; +mod tile_stream_cmds; +mod tilejson; pub mod tiles; diff --git a/crates/utiles-cli/src/commands/rimraf.rs b/crates/utiles-cli/src/commands/rimraf.rs new file mode 100644 index 00000000..58a3c146 --- /dev/null +++ b/crates/utiles-cli/src/commands/rimraf.rs @@ -0,0 +1,124 @@ +use std::cell::Cell; +use std::path::Path; + +use futures::stream::{self, StreamExt}; +use tokio::fs; +use tracing::error; +use walkdir::{DirEntry, WalkDir}; + +use crate::args::RimrafArgs; + +// iter files... + +#[derive(Debug)] +pub struct RimrafStats { + pub nfiles: Cell, + pub ndirs: Cell, + pub nbytes: Cell, +} + +impl RimrafStats { + pub fn new() -> Self { + Self { + nfiles: Cell::new(0), + ndirs: Cell::new(0), + nbytes: Cell::new(0), + } + } + pub fn inc_nfiles(&self) { + self.nfiles.set(self.nfiles.get() + 1); + } + + // pub fn inc_ndirs(&self) { + // self.ndirs.set(self.ndirs.get() + 1); + // } + + pub fn inc_nbytes(&self, nbytes: u64) { + self.nbytes.set(self.nbytes.get() + nbytes); + } +} + +#[derive(Debug)] +pub struct Rimrafer { + pub cfg: RimrafArgs, + pub stats: RimrafStats, +} + +impl Rimrafer { + pub fn new(args: RimrafArgs) -> Self { + Self { + cfg: args, + stats: RimrafStats::new(), + } + } + + pub async fn rm_file_stats(&self, file: DirEntry) { + let path = file.path(); + let nbytes = fs::metadata(path).await.unwrap().len(); + self.stats.inc_nfiles(); + self.stats.inc_nbytes(nbytes); + } + + pub async fn rm_file(&self, file: DirEntry) { + if self.cfg.size { + self.rm_file_stats(file).await; + self.print_stats_1000(); + return; + } + let path = file.path(); + fs::remove_file(path).await.unwrap(); + self.stats.inc_nfiles(); + self.print_stats_1000(); + } + + // pub async fn rm_dir(&self, dir: DirEntry) { + // let path = dir.path(); + // fs::remove_dir_all(path).await.unwrap(); + // self.stats.inc_ndirs(); + // } + + pub fn stats_str(&self) -> String { + format!( + "nfiles: {}, ndirs: {}, nbytes: {}", + self.stats.nfiles.get(), + self.stats.ndirs.get(), + self.stats.nbytes.get() + ) + } + + pub fn print_stats(&self) { + println!("stats: {:?}", self.stats_str()); + } + + pub fn print_stats_1000(&self) { + if self.stats.nfiles.get() % 1000 == 0 { + self.print_stats(); + } + } +} + +pub async fn rimraf_main(args: RimrafArgs) { + println!("rimraf_main: args: {args:?}"); + // check that dirpath exists + let dirpath = Path::new(&args.dirpath); + if !dirpath.exists() { + error!("dirpath does not exist: {:?}", dirpath); + return; + } + + let files_iter = WalkDir::new(args.clone().dirpath.clone()) + .contents_first(true) + .into_iter() + .filter_map(std::result::Result::ok) + .filter(|e| e.file_type().is_file()); + + let rmrfer = Rimrafer::new(args); + + let s = stream::iter(files_iter); + s.for_each_concurrent(10, |file| async { + rmrfer.rm_file(file).await; + }) + .await; + fs::remove_dir_all(&rmrfer.cfg.dirpath).await.unwrap(); + rmrfer.print_stats(); +} diff --git a/crates/utiles-cli/src/shapes.rs b/crates/utiles-cli/src/commands/shapes.rs similarity index 95% rename from crates/utiles-cli/src/shapes.rs rename to crates/utiles-cli/src/commands/shapes.rs index 539c8486..a8465f3b 100644 --- a/crates/utiles-cli/src/shapes.rs +++ b/crates/utiles-cli/src/commands/shapes.rs @@ -205,7 +205,7 @@ pub fn shapes_main(args: ShapesArgs) { if !first { println!(","); } - println!("{}", f.to_json()); + println!(" {}", f.to_json()); first = false; } else { if args.seq { @@ -222,13 +222,4 @@ pub fn shapes_main(args: ShapesArgs) { println!("]"); println!("}}"); } - // for tile in tiles { - // let f = tile.feature( - // &feature_options - // ).unwrap(); - // lons.extend(f.bbox_lons()); - // lats.extend(f.bbox_lats()); - // - // println!("{}", f.to_json()); - // } } diff --git a/crates/utiles-cli/src/commands/tile_stream_cmds.rs b/crates/utiles-cli/src/commands/tile_stream_cmds.rs new file mode 100644 index 00000000..15ad168b --- /dev/null +++ b/crates/utiles-cli/src/commands/tile_stream_cmds.rs @@ -0,0 +1,84 @@ +use tracing::{debug, error}; +use utiles::parsing::parse_bbox; +use utiles::{bounding_tile, Tile, TileLike}; + +use crate::args::TileFmtArgs; +use crate::stdinterator_filter; + +pub fn neighbors_main(args: TileFmtArgs) { + let lines = stdinterator_filter::stdin_filtered(args.inargs.input); + let tiles = lines.map(|l| Tile::from_json(&l.unwrap())); + for tile in tiles { + let neighbors = tile.neighbors(); + for neighbor in neighbors { + let rs = if args.fmtopts.seq { "\x1e\n" } else { "" }; + println!("{}{}", rs, neighbor.json_arr()); + } + } +} + +pub fn bounding_tile_main(args: TileFmtArgs) { + let lines = stdinterator_filter::stdin_filtered(args.inargs.input); + let bboxes = lines.map(|l| { + let s = l.unwrap(); + debug!("l: {:?}", s); + parse_bbox(&s).unwrap() + }); + for bbox in bboxes { + let tile = bounding_tile(bbox, None); + // let tile = Tile::from_bbox(&bbox, zoom); + let rs = if args.fmtopts.seq { "\x1e\n" } else { "" }; + println!("{}{}", rs, tile.json_arr()); + } +} + +pub fn pmtileid_main(args: TileFmtArgs) { + let lines = stdinterator_filter::stdin_filtered(args.inargs.input); + for line in lines { + // if the line bgins w '[' treat as tile + let lstr = line.unwrap(); + if lstr.starts_with('[') { + // treat as tile + let tile = Tile::from_json_arr(&lstr); + println!("{}", tile.pmtileid()); + } else { + // treat as pmtileid + let pmid: u64 = lstr.parse().unwrap(); + let tile = Tile::from_pmid(pmid); + if tile.is_err() { + error!("Invalid pmtileid: {pmid}"); + println!("Invalid pmtileid: {pmid}"); + } else { + println!("{}", tile.unwrap().json_arr()); + } + } + } +} + +pub fn quadkey_main(args: TileFmtArgs) { + let lines = stdinterator_filter::stdin_filtered(args.inargs.input); + for line in lines { + // if the line begins w/ '['/'{' treat as json-tile + // otherwise treat as quadkey + let lstr = line.unwrap(); + let first_char = lstr.chars().next().unwrap(); + match first_char { + '[' | '{' => { + // treat as tile + let tile = Tile::from_json_arr(&lstr); + println!("{}", tile.quadkey()); + } + _ => { + // treat as quadkey + let qk = lstr; + let tile = Tile::from_quadkey(&qk); + if tile.is_err() { + error!("Invalid quadkey: {qk}"); + println!("Invalid quadkey: {qk}"); + } else { + println!("{}", tile.unwrap().json_arr()); + } + } + } + } +} diff --git a/crates/utiles-cli/src/commands/tilejson.rs b/crates/utiles-cli/src/commands/tilejson.rs new file mode 100644 index 00000000..13aee425 --- /dev/null +++ b/crates/utiles-cli/src/commands/tilejson.rs @@ -0,0 +1,31 @@ +use std::path::Path; + +use tracing::debug; + +use utilejson::tilejson_stringify; +use utilesqlite::Mbtiles; + +use crate::args::TilejsonArgs; + +pub fn tilejson_main(args: &TilejsonArgs) { + debug!("tilejson: {}", args.common.filepath); + // check that filepath exists and is file + let filepath = Path::new(&args.common.filepath); + assert!( + filepath.exists(), + "File does not exist: {}", + filepath.display() + ); + assert!( + filepath.is_file(), + "Not a file: {filepath}", + filepath = filepath.display() + ); + let mbtiles: Mbtiles = Mbtiles::from(filepath); + let mut tj = mbtiles.tilejson().unwrap(); + if !args.tilestats { + tj.other.remove("tilestats"); + } + let s = tilejson_stringify(&tj, Option::from(!args.common.min)); + println!("{s}"); +} diff --git a/crates/utiles-cli/src/commands/tiles.rs b/crates/utiles-cli/src/commands/tiles.rs index d73626b9..97de2d24 100644 --- a/crates/utiles-cli/src/commands/tiles.rs +++ b/crates/utiles-cli/src/commands/tiles.rs @@ -1,20 +1,45 @@ -use crate::args::TilesArgs; -use crate::stdinterator_filter::stdin_filtered; use std::io; use std::io::Write; + use tracing::debug; -use utiles::parsing::parse_bbox; + +use utiles::parsing::parse_bbox_ext; use utiles::tiles; use utiles::zoom::ZoomOrZooms; +use utiles::{Tile, TileLike}; + +use crate::args::TilesArgs; +use crate::stdinterator_filter::stdin_filtered; + +pub enum TileFmt { + Arr, + Obj, + // Tms, + // Pmtileid, + // Quadkey, +} + +pub trait TileStringFormatter { + fn format_tile(&self, tile: &Tile) -> String; +} + +impl TileStringFormatter for TileFmt { + fn format_tile(&self, tile: &Tile) -> String { + match self { + TileFmt::Arr => tile.json_arr(), + TileFmt::Obj => tile.json_obj(), + } + } +} pub fn tiles_main(args: TilesArgs, loop_fn: Option<&dyn Fn()>) { - let lines = stdin_filtered(args.input); + let lines = stdin_filtered(args.inargs.input); let mut stdout = io::stdout(); let tiles = lines .map(|l| { let s = l.unwrap(); debug!("l: {:?}", s); - parse_bbox(&s).unwrap() + parse_bbox_ext(&s).unwrap() }) .flat_map(|b| { tiles( @@ -23,11 +48,16 @@ pub fn tiles_main(args: TilesArgs, loop_fn: Option<&dyn Fn()>) { ) }) .enumerate(); - // let bboxes = lines + + let tile_fmt = if args.fmtopts.obj { + TileFmt::Obj + } else { + TileFmt::Arr + }; + + let rs = if args.fmtopts.seq { "\x1e\n" } else { "" }; for (i, tile) in tiles { - let rs = if args.seq { "\x1e\n" } else { "" }; - // println!("{}{}", rs, tile.json_arr()); - writeln!(stdout, "{}{}", rs, tile.json_arr()).unwrap(); + writeln!(stdout, "{}{}", rs, tile_fmt.format_tile(&tile)).unwrap(); // call loop_fn if it's defined every 1000 iterations for signal break if i % 1024 == 0 { stdout.flush().unwrap(); diff --git a/crates/utiles-cli/src/find.rs b/crates/utiles-cli/src/find.rs new file mode 100644 index 00000000..1bf5a044 --- /dev/null +++ b/crates/utiles-cli/src/find.rs @@ -0,0 +1,50 @@ +use std::path::PathBuf; + +use globset::{Glob, GlobSetBuilder}; +use ignore::WalkBuilder; +use tracing::warn; + +fn is_dir(path: &str) -> bool { + let path = std::path::Path::new(path); + path.is_dir() +} + +fn is_file(path: &str) -> bool { + let path = std::path::Path::new(path); + path.is_file() +} + +pub fn find_filepaths(fspaths: &[String]) -> Vec { + let fspath = fspaths[0].clone(); + + let mut glob_builder = GlobSetBuilder::new(); + let glob = Glob::new("**/*.{mbtiles,sqlite,sqlite3}").unwrap(); + glob_builder.add(glob); + let globset = glob_builder.build().unwrap(); + + // filepaths + let mut filepaths: Vec = vec![]; + + if is_file(&fspath) { + filepaths.push(PathBuf::from(fspath)); + } else if is_dir(&fspath) { + let dirpath = PathBuf::from(fspath).canonicalize().unwrap(); + let walk_builder = WalkBuilder::new(dirpath); + for result in walk_builder.build().filter_map(std::result::Result::ok) { + if !result.file_type().unwrap().is_file() { + continue; + } + match result.path().to_str() { + Some(path) => { + if globset.is_match(path) { + filepaths.push(path.into()); + } + } + None => { + warn!("Unable to convert path to string: {:?}", result.path()); + } + } + } + } + filepaths +} diff --git a/crates/utiles-cli/src/lib.rs b/crates/utiles-cli/src/lib.rs index d8209f92..8312358b 100644 --- a/crates/utiles-cli/src/lib.rs +++ b/crates/utiles-cli/src/lib.rs @@ -10,8 +10,7 @@ mod args; mod cli; mod commands; -mod lint; -mod shapes; +mod find; mod stdinterator; mod stdinterator_filter; diff --git a/crates/utiles-cli/src/stdinterator_filter.rs b/crates/utiles-cli/src/stdinterator_filter.rs index b4822519..56113a47 100644 --- a/crates/utiles-cli/src/stdinterator_filter.rs +++ b/crates/utiles-cli/src/stdinterator_filter.rs @@ -9,6 +9,5 @@ pub fn stdin_filtered( .filter(|l| !l.is_err()) .filter(|l| !l.as_ref().unwrap().is_empty()) .filter(|l| l.as_ref().unwrap() != "\x1e"); - - Box::new(filtered_lines) as _ + Box::new(filtered_lines) } diff --git a/crates/utiles-dev/Cargo.toml b/crates/utiles-dev/Cargo.toml new file mode 100644 index 00000000..526c611f --- /dev/null +++ b/crates/utiles-dev/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "utiles-dev" +edition.workspace = true +version.workspace = true +homepage.workspace = true +documentation.workspace = true +repository.workspace = true +authors.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +name = "utiles_dev" +path = "src/lib.rs" + +[[bin]] +name = "utdev" +path = "src/main.rs" + +[dependencies] +utiles = { path = "../utiles" } +utilesqlite = { path = "../utilesqlite" } +utiles-cli = { path = "../utiles-cli" } +anyhow.workspace = true +fast_hilbert.workspace = true +geo-types.workspace = true +geojson.workspace = true +rusqlite.workspace = true +serde.workspace = true +serde_json.workspace = true +thiserror.workspace= true +tilejson.workspace = true +tokio.workspace = true +tracing-subscriber.workspace = true +tracing.workspace = true +sqlx = { version = "0.7.2", features = ["sqlite", "runtime-tokio", "macros"] } +futures = "0.3.29" +geozero = { version = "0.11.0", features = ["with-mvt", "with-wkb"] } +deadpool-sqlite = { version = "0.7.0", features = ["tracing"] } diff --git a/crates/utiles-dev/src/lib.rs b/crates/utiles-dev/src/lib.rs new file mode 100644 index 00000000..e3fe34b6 --- /dev/null +++ b/crates/utiles-dev/src/lib.rs @@ -0,0 +1,3 @@ +// mod ugeojson; + +async fn rimraf_main() {} diff --git a/crates/utiles-dev/src/main.rs b/crates/utiles-dev/src/main.rs new file mode 100644 index 00000000..e7d5be94 --- /dev/null +++ b/crates/utiles-dev/src/main.rs @@ -0,0 +1,138 @@ +use futures::TryStreamExt; +use geozero; +use geozero::mvt::{self, tile, Message, Tile}; +use geozero::{ProcessToJson, ToJson}; +use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions}; +use sqlx::{ + query, query_as, query_as_unchecked, ConnectOptions, Executor, FromRow, Statement, +}; +use std::fmt::Pointer; + +// #[derive(Debug, FromRow)] +// struct MetadataRow { +// name: String, +// value: String, +// } +#[derive(Debug, FromRow)] +struct MetadataRow2 { + tile_row: i32, + // tile_column: i32, + // zoom_level: i32, + // tile_data: Vec, +} +#[derive(Debug, FromRow)] +struct MetadataRow { + tile_row: i32, + tile_column: i32, + zoom_level: i32, + tile_data: Vec, +} + +fn mvt_dev() { + let filepath = "D:\\utiles\\crates\\utiles-dev\\12665.vector.pbf"; + // read to vec of bytes + let bytes = std::fs::read(filepath).unwrap(); + + println!("bytes: {:?}", bytes.len()); + // let buf = bytes.as_slice(); + + let mut cursor = std::io::Cursor::new(bytes.as_slice()); + + let mt = Tile::decode(cursor).unwrap(); + + println!("mt: {:?}", mt); + // let t = + + // let gj = mt.to_json().unwrap(); + + let num_layers = mt.layers.len(); + println!("num_layers: {:?}", num_layers); + + // mt.layers + // mt.layers.into_iter().map( + // |layer| { + // let mut l = layer.clone(); + // println!("l: {:?}", l); + // let s = l.to_json().unwrap(); + // println!("s:"); + // println!("{}", s); + // } + // ).collect::>(); + + // println!("gj: {:?}", gj); + // number of layers in tile + // let mtjson = serde_json::to_string(&mt).unwrap(); + + // let gj = geozero::mvt::to_geojson(&mt).unwrap(); + // println!("mtjson: {:?}", mtjson); +} + +async fn sqlite_deadpool_test() { + println!("sqlite_deadpool_test"); + let file = "D:\\blue-marble\\blue-marble.mbtiles.NOPE"; + let mbta = utilesqlite::MbtilesAsync::open(file).await.unwrap(); + + let tj = mbta.tilejson().await; + + match tj { + Ok(t) => { + println!("tj: {t:?}"); + } + Err(e) => { + println!("e: {:?}", e); + } + } +} + +async fn sqlxing() { + let file = "D:\\blue-marble\\blue-marble.mbtiles"; + + let copts = SqliteConnectOptions::new() + .filename(file) + .create_if_missing(true); + let mut c = copts.connect().await.unwrap(); + + let pool = SqlitePoolOptions::new() + .max_connections(5) + .connect_with(copts) + .await + .unwrap(); + + // timing + // start + let start = std::time::Instant::now(); + // let tthingydickr = query_as::<_, MetadataRow>("SELECT * FROM tiles"); + let mut r = query_as::<_, MetadataRow>("SELECT * FROM tiles").fetch(&pool); + while let Some(row) = r.try_next().await.unwrap() { + // println!("row: {:?}", row); + } + + // end + let end = std::time::Instant::now(); + println!("time: {:?}", end.duration_since(start)); + + // as uno fetch + let start2 = std::time::Instant::now(); + let r2 = query_as::<_, MetadataRow2>("SELECT tile_row FROM tiles") + .fetch_all(&pool) + .await + .unwrap(); + let end2 = std::time::Instant::now(); + println!("r2: {:?}", r2.len()); + println!("time: {:?}", end2.duration_since(start2)); +} +#[tokio::main] +async fn main() { + println!("utiles ~ dev"); + + mvt_dev(); + + sqlite_deadpool_test().await; + + sqlxing().await; + + // let res = r.iter().map(|row| { + // println!("row:j"); + // }).collect::>(); + // println!("r: {:?}", r); +} diff --git a/crates/utiles-dev/src/ugeojson.rs b/crates/utiles-dev/src/ugeojson.rs new file mode 100644 index 00000000..b114843b --- /dev/null +++ b/crates/utiles-dev/src/ugeojson.rs @@ -0,0 +1,80 @@ +use serde::{Deserialize, Serialize}; + +#[allow(dead_code)] + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +struct Coordinate2d(f64, f64); +#[derive(Debug, PartialEq, Serialize, Deserialize)] +struct Coordinate3d(f64, f64, f64); +#[derive(Debug, PartialEq, Serialize, Deserialize)] +struct Coordinate4d(f64, f64, f64, f64); + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum GeojsonCoordinate { + Coordinate2d(Coordinate2d), + Coordinate3d(Coordinate3d), +} + +pub type LineStringGeneric = Vec; +pub type LineString2d = Vec; +pub type LineString3d = Vec; +pub type LineString = Vec; + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct PointGeometry { + pub r#type: String, + pub coordinates: GeojsonCoordinate, +} + +pub type PointType = GeojsonCoordinate; +pub type MultiPointType = Vec; +pub type LineStringType = LineString; + +pub enum GeometryTypeGeneric { + Point(TCoordinate), + MultiPoint(Vec), + LineString(Vec), + // MultiLineString (Vec>), + // Polygon (Vec>), + // MultiPolygon (Vec>>), + // GeometryCollection (Vec>), +} +pub type Geometry2d = GeometryTypeGeneric; +pub type Geometry3d = GeometryTypeGeneric; +pub type Geometry = GeometryTypeGeneric; + +// pub enum GeometryTypeGeneric < TCoordinate > + +// > { +// Point(PointType), +// MultiPoint (MultiPointType), +// LineString (LineStringType), +// // MultiLineString (MultiLineStringType), +// // Polygon (PolygonType), +// // MultiPolygon, +// // GeometryCollection, +// } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn sometest() { + assert_eq!(1, 1); + + let mixed = vec![ + GeojsonCoordinate::Coordinate2d(Coordinate2d(1.0, 2.0)), + GeojsonCoordinate::Coordinate3d(Coordinate3d(3.0, 4.0, 5.0)), + ]; + + let string = serde_json::to_string(&mixed).unwrap(); + println!("{}", string); + assert_eq!(string, "[[1.0,2.0],[3.0,4.0,5.0]]"); + + let unstring: Vec = serde_json::from_str(&string).unwrap(); + println!("{:?}", unstring); + assert_eq!(unstring, mixed); + } +} diff --git a/crates/utiles/Cargo.lock b/crates/utiles/Cargo.lock deleted file mode 100644 index afbf448c..00000000 --- a/crates/utiles/Cargo.lock +++ /dev/null @@ -1,278 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "fast_hilbert" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ec2bbe15af87954c739e236021f4411766c0f2b9c4a5f0b9317bcf6048ebf8" -dependencies = [ - "num-traits", -] - -[[package]] -name = "geo-types" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567495020b114f1ce9bed679b29975aa0bfae06ac22beacd5cfde5dabe7b05d6" -dependencies = [ - "approx", - "num-traits", - "serde", -] - -[[package]] -name = "geojson" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d728c1df1fbf328d74151efe6cb0586f79ee813346ea981add69bd22c9241b" -dependencies = [ - "geo-types", - "log", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "proc-macro2" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "serde" -version = "1.0.192" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.192" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "serde_json" -version = "1.0.108" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_tuple" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f025b91216f15a2a32aa39669329a475733590a015835d1783549a56d09427" -dependencies = [ - "serde", - "serde_tuple_macros", -] - -[[package]] -name = "serde_tuple_macros" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4076151d1a2b688e25aaf236997933c66e18b870d0369f8b248b8ab2be630d7e" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "tilejson" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a16212e5ea60f2b406835981338a1df9b206fab312e3470502d60f69e590a9c9" -dependencies = [ - "serde", - "serde_json", - "serde_tuple", -] - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "utiles" -version = "0.0.1" -dependencies = [ - "anyhow", - "fast_hilbert", - "geo-types", - "geojson", - "serde", - "serde_json", - "thiserror", - "tilejson", - "tracing", -] diff --git a/crates/utiles/Cargo.toml b/crates/utiles/Cargo.toml index 67e3a45f..0799dcd2 100644 --- a/crates/utiles/Cargo.toml +++ b/crates/utiles/Cargo.toml @@ -12,7 +12,6 @@ homepage = "https://github.com/jessekrubin/utiles" repository = "https://github.com/jessekrubin/utiles" [dependencies] -anyhow.workspace = true fast_hilbert.workspace = true geo-types.workspace = true geojson.workspace = true @@ -20,4 +19,3 @@ serde.workspace = true serde_json.workspace = true thiserror.workspace = true tilejson.workspace = true -tracing.workspace = true diff --git a/crates/utiles/src/bbox.rs b/crates/utiles/src/bbox.rs index cd6939c4..6a5fef2a 100644 --- a/crates/utiles/src/bbox.rs +++ b/crates/utiles/src/bbox.rs @@ -1,6 +1,7 @@ use crate::lnglat::LngLat; use crate::parsing::parse_bbox; use crate::tile::Tile; +use crate::tile_like::TileLike; use geo_types::Coord; use serde::{Deserialize, Serialize}; use tilejson::Bounds; @@ -264,16 +265,13 @@ impl From<&String> for BBox { // remove leading and trailing quotes let s = s.trim_matches('"'); // let value: Value = serde_json::from_str(&s).unwrap(); - let result = match parse_bbox(s) { + match parse_bbox(s) { Ok(bbox) => bbox, Err(e) => { println!("ERROR: {e}"); BBox::world_planet() } - }; - result - // let tuple: BBoxTuple = serde_json::from_str(s).unwrap(); - // self::BBox::from(tuple) + } } } diff --git a/crates/utiles/src/fns.rs b/crates/utiles/src/fns.rs index 9b62d35b..a660fefa 100644 --- a/crates/utiles/src/fns.rs +++ b/crates/utiles/src/fns.rs @@ -1,14 +1,17 @@ +use std::collections::{HashMap, HashSet}; +use std::f64::consts::PI; +use std::num::FpCategory; + +use geo_types::coord; + use crate::bbox::{BBox, WebMercatorBbox}; use crate::constants::{EARTH_CIRCUMFERENCE, EARTH_RADIUS, LL_EPSILON}; use crate::sibling_relationship::SiblingRelationship; use crate::tile_range::{TileRange, TileRanges}; +use crate::{LngLat, Tile}; +// use crate::TileLike; use crate::utile; use crate::zoom::ZoomOrZooms; -use crate::{LngLat, Tile}; -use geo_types::coord; -use std::collections::{HashMap, HashSet}; -use std::f64::consts::PI; -use std::num::FpCategory; #[must_use] pub fn ul(x: u32, y: u32, z: u8) -> LngLat { @@ -56,10 +59,17 @@ pub fn valid(x: u32, y: u32, z: u8) -> bool { } #[must_use] +#[inline] pub fn flipy(y: u32, z: u8) -> u32 { 2_u32.pow(u32::from(z)) - 1 - y } +#[must_use] +#[inline] +pub fn yflip(y: u32, z: u8) -> u32 { + flipy(y, z) +} + #[must_use] pub fn bbox2zoom(bbox: (u32, u32, u32, u32)) -> u8 { let max_zoom = 28; @@ -565,9 +575,7 @@ fn merge(merge_set: &HashSet) -> (HashSet, bool) { let mut upwards_merge: HashMap> = HashMap::new(); for tile in merge_set { let tile_parent = tile.parent(None); - let children_set = upwards_merge - .entry(tile_parent) - .or_insert_with(HashSet::new); + let children_set = upwards_merge.entry(tile_parent).or_default(); children_set.insert(*tile); } let mut current_tileset: Vec = Vec::new(); diff --git a/crates/utiles/src/gdal.rs b/crates/utiles/src/gdal.rs new file mode 100644 index 00000000..f4875c1f --- /dev/null +++ b/crates/utiles/src/gdal.rs @@ -0,0 +1,72 @@ +/// A geotransform is an affine transformation from the image coordinate space +/// (row, column), also known as (pixel, line) to the georeferenced coordinate +/// space (projected or geographic coordinates). +/// +/// A geotransform consists in a set of 6 coefficients: +/// +/// GT(0) x-coordinate of the upper-left corner of the upper-left pixel. +/// GT(1) w-e pixel resolution / pixel width. +/// GT(2) row rotation (typically zero). +/// GT(3) y-coordinate of the upper-left corner of the upper-left pixel. +/// GT(4) column rotation (typically zero). +/// GT(5) n-s pixel resolution / pixel height (negative value for a north-up image). +pub struct GeoTransform { + /// x-coordinate of the upper-left corner of the upper-left pixel. + pub gt0: f64, + /// w-e pixel resolution / pixel width. + pub gt1: f64, + /// row rotation (typically zero). + pub gt2: f64, + /// y-coordinate of the upper-left corner of the upper-left pixel. + pub gt3: f64, + /// column rotation (typically zero). + pub gt4: f64, + /// n-s pixel resolution / pixel height (negative value for a north-up image). + pub gt5: f64, +} + +impl GeoTransform { + #[must_use] + pub fn new(gt0: f64, gt1: f64, gt2: f64, gt3: f64, gt4: f64, gt5: f64) -> Self { + GeoTransform { + gt0, + gt1, + gt2, + gt3, + gt4, + gt5, + } + } + + pub fn optzoom(&self) -> u8 { + let equator = 2.0 * std::f64::consts::PI * 6_378_137.0; // 2 * pi * radius of earth in meters + let resolution = self.gt1 * (equator / 360.0); + let zoom_level = (equator / 256.0) / resolution; // Assuming pixel_size is 256 as in the previous example + (zoom_level.log2().min(20.0).floor() + 0.5) as u8 + } +} + +impl From<(f64, f64, f64, f64, f64, f64)> for GeoTransform { + fn from(gt: (f64, f64, f64, f64, f64, f64)) -> Self { + GeoTransform::new(gt.0, gt.1, gt.2, gt.3, gt.4, gt.5) + } +} + +#[must_use] +pub fn geotransform2optzoom(geotransform: (f64, f64, f64, f64, f64, f64)) -> u8 { + let gt = GeoTransform::from(geotransform); + gt.optzoom() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_geotransform2optzoom() { + let optz = geotransform2optzoom(( + -77.000138, 0.000278, 0.0, 26.0001389, 0.0, -0.000278, + )); + assert_eq!(optz, 12); + } +} diff --git a/crates/utiles/src/geostats.rs b/crates/utiles/src/geostats.rs new file mode 100644 index 00000000..37c7da80 --- /dev/null +++ b/crates/utiles/src/geostats.rs @@ -0,0 +1,47 @@ +// converted by chadwick-general-purpose-tool from geostats schema. +// ref: from https://github.com/mapbox/mapbox-geostats +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TileStats { + pub layer_count: f64, + pub layers: Vec, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Layer { + pub layer: String, + pub count: f64, + pub geometry: GeometryType, + pub attribute_count: f64, + pub attributes: Vec, +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum GeometryType { + Point, + LineString, + Polygon, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Attribute { + pub attribute: String, + pub count: f64, + pub r#type: DataType, + pub values: Vec, + pub min: Option, + pub max: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum DataType { + String, + Number, + Boolean, + Null, + Mixed, +} diff --git a/crates/utiles/src/lib.rs b/crates/utiles/src/lib.rs index 0d16d10b..f00170c5 100644 --- a/crates/utiles/src/lib.rs +++ b/crates/utiles/src/lib.rs @@ -2,6 +2,7 @@ #![deny(clippy::perf)] #![deny(clippy::style)] #![deny(clippy::correctness)] +#![warn(clippy::must_use_candidate)] #![allow(clippy::module_name_repetitions)] #![allow(clippy::missing_panics_doc)] #![allow(clippy::missing_errors_doc)] @@ -12,10 +13,13 @@ pub use crate::fns::*; pub use crate::quadkey::*; pub use lnglat::LngLat; pub use tile::Tile; +pub use tile_like::TileLike; pub mod bbox; pub mod constants; pub mod fns; +mod gdal; pub mod geojson; +mod geostats; pub mod libtiletype; pub mod lint_error; pub mod lnglat; @@ -26,13 +30,18 @@ pub mod projection; pub mod quadkey; pub mod sibling_relationship; pub mod tile; +pub mod tile_data_row; mod tile_feature; +mod tile_like; pub mod tile_range; mod tile_tuple; +mod tilecrz; pub mod tilejson; pub mod traits; pub mod zoom; +pub use gdal::geotransform2optzoom; + pub const VERSION: &str = env!("CARGO_PKG_VERSION"); /// Tile macro to create a new tile. diff --git a/crates/utiles/src/libtiletype.rs b/crates/utiles/src/libtiletype.rs index c0cb9748..872998ef 100644 --- a/crates/utiles/src/libtiletype.rs +++ b/crates/utiles/src/libtiletype.rs @@ -21,47 +21,15 @@ pub const TILETYPE_WEBP: usize = 7; #[must_use] pub fn tiletype(buffer: &[u8]) -> TileType { if buffer.len() >= 8 { - if buffer[0] == 0x89 - && buffer[1] == 0x50 - && buffer[2] == 0x4e - && buffer[3] == 0x47 - && buffer[4] == 0x0d - && buffer[5] == 0x0a - && buffer[6] == 0x1a - && buffer[7] == 0x0a - { - return TileType::Png; - } else if buffer[0] == 0xff - && buffer[1] == 0xd8 - && buffer[buffer.len() - 2] == 0xff - && buffer[buffer.len() - 1] == 0xd9 - { - return TileType::Jpg; - } else if buffer[0] == 0x47 - && buffer[1] == 0x49 - && buffer[2] == 0x46 - && buffer[3] == 0x38 - && (buffer[4] == 0x39 || buffer[4] == 0x37) - && buffer[5] == 0x61 - { - return TileType::Gif; - } else if buffer[0] == 0x52 - && buffer[1] == 0x49 - && buffer[2] == 0x46 - && buffer[3] == 0x46 - && buffer[8] == 0x57 - && buffer[9] == 0x45 - && buffer[10] == 0x42 - && buffer[11] == 0x50 - { - return TileType::Webp; - } else if buffer[0] == 0x78 && buffer[1] == 0x9c { - return TileType::Pbf; - } else if buffer[0] == 0x1f && buffer[1] == 0x8b { - return TileType::Pbfgz; - // if starts with '{' or '[' json - } else if buffer[0] == 0x7b || buffer[0] == 0x5b { - return TileType::Json; + match buffer { + v if v.starts_with(b"\x89PNG\r\n\x1a\n") => return TileType::Png, + v if v.starts_with(b"\xff\xd8") => return TileType::Jpg, + v if v.starts_with(b"GIF87a") || v.starts_with(b"GIF89a") => return TileType::Gif, + v if v.starts_with(b"RIFF") && &v[8..12] == b"WEBP" => return TileType::Webp, + v if v.starts_with(b"\x1f\x8b") => return TileType::Pbfgz, + v if v.starts_with(b"\x78\x9c") => return TileType::Pbf, + v if v.starts_with(b"{") || v.starts_with(b"[") => return TileType::Json, + _ => {} } } TileType::Unknown diff --git a/crates/utiles/src/mbtiles/metadata2map.rs b/crates/utiles/src/mbtiles/metadata2map.rs index 297c9c62..950aae2b 100644 --- a/crates/utiles/src/mbtiles/metadata2map.rs +++ b/crates/utiles/src/mbtiles/metadata2map.rs @@ -7,12 +7,17 @@ pub fn metadata2duplicates( rows: Vec, ) -> HashMap> { rows.into_iter() - .fold(HashMap::new(), |mut acc, row| { - acc.entry(row.name.clone()) - .or_insert_with(Vec::new) - .push(row); - acc - }) + .fold( + HashMap::new(), + |mut acc: std::collections::HashMap< + std::string::String, + Vec, + >, + row| { + acc.entry(row.name.clone()).or_default().push(row); + acc + }, + ) .into_iter() .filter(|(_k, v)| v.len() > 1) .collect() diff --git a/crates/utiles/src/mbtiles/metadata2tilejson.rs b/crates/utiles/src/mbtiles/metadata2tilejson.rs index d0afcecd..3f0c4498 100644 --- a/crates/utiles/src/mbtiles/metadata2tilejson.rs +++ b/crates/utiles/src/mbtiles/metadata2tilejson.rs @@ -3,17 +3,15 @@ use std::fmt::Display; use std::str::FromStr; use serde_json::{Value as JSONValue, Value}; +use tilejson::{Bounds, Center, tilejson, TileJSON}; +use crate::geostats::TileStats; use crate::mbtiles::metadata_row::MbtilesMetadataRow; -use tilejson::{tilejson, Bounds, Center, TileJSON}; -use tracing::{info, warn}; -fn to_val(val: Result, title: &str) -> Option { +fn to_val(val: Result) -> Option { match val { Ok(v) => Some(v), Err(_err) => { - // let name = &self.filename; - warn!("Unable to parse metadata {title}"); None } } @@ -25,7 +23,6 @@ pub fn metadata2tilejson( metadata: Vec, ) -> Result> { let mut tj = tilejson! {tiles : vec![]}; - // let mut layer_type: Option = None; let mut json: Option = None; for row in metadata { @@ -34,23 +31,20 @@ pub fn metadata2tilejson( match name.as_ref() { "name" => tj.name = Some(value), "version" => tj.version = Some(value), - "bounds" => tj.bounds = to_val(Bounds::from_str(value.as_str()), &name), - "center" => tj.center = to_val(Center::from_str(value.as_str()), &name), - "minzoom" => tj.minzoom = to_val(value.parse(), &name), - "maxzoom" => tj.maxzoom = to_val(value.parse(), &name), + "bounds" => tj.bounds = to_val(Bounds::from_str(value.as_str())), + "center" => tj.center = to_val(Center::from_str(value.as_str())), + "minzoom" => tj.minzoom = to_val(value.parse()), + "maxzoom" => tj.maxzoom = to_val(value.parse()), "description" => tj.description = Some(value), "attribution" => tj.attribution = Some(value), // "type" => layer_type = Some(value), "legend" => tj.legend = Some(value), "template" => tj.template = Some(value), - "json" => json = to_val(serde_json::from_str(&value), &name), + "json" => json = to_val(serde_json::from_str(&value)), "format" | "generator" => { tj.other.insert(name, Value::String(value)); } _ => { - // let file = &filename; - // info!("{file} has an unrecognized metadata value {name}={value}"); - info!("unrecognized metadata value {name}={value}"); tj.other.insert(name, Value::String(value)); } } @@ -60,10 +54,13 @@ pub fn metadata2tilejson( if let Some(value) = obj.remove("vector_layers") { if let Ok(v) = serde_json::from_value(value) { tj.vector_layers = Some(v); - } else { - warn!( - "Unable to parse metadata vector_layers value", - // self.filename + } + } + if let Some(value) = obj.remove("tilestats") { + if let Ok(v) = serde_json::from_value::(value) { + tj.other.insert( + "tilestats".parse().unwrap(), + serde_json::to_value(v).unwrap(), ); } } diff --git a/crates/utiles/src/mbtiles/mod.rs b/crates/utiles/src/mbtiles/mod.rs index 56ffa1ec..fc641a29 100644 --- a/crates/utiles/src/mbtiles/mod.rs +++ b/crates/utiles/src/mbtiles/mod.rs @@ -1,11 +1,15 @@ -mod metadata2map; -mod metadata2tilejson; -pub mod metadata_row; -mod minzoom_maxzoom; +pub use tiles_row::MbtTileRow; pub use crate::mbtiles::metadata2map::{metadata2duplicates, metadata2map}; pub use crate::mbtiles::metadata2tilejson::metadata2tilejson; pub use crate::mbtiles::metadata_row::{MbtilesMetadataRow, MbtilesMetadataRows}; pub use crate::mbtiles::minzoom_maxzoom::MinZoomMaxZoom; +mod metadata2map; + +mod metadata2tilejson; +pub mod metadata_row; +mod minzoom_maxzoom; +mod tiles_row; + pub const MBTILES_MAGIC_NUMBER: u32 = 0x4d50_4258; diff --git a/crates/utiles/src/mbtiles/tiles_row.rs b/crates/utiles/src/mbtiles/tiles_row.rs new file mode 100644 index 00000000..9f8daa04 --- /dev/null +++ b/crates/utiles/src/mbtiles/tiles_row.rs @@ -0,0 +1,51 @@ +use crate::libtiletype::tiletype_str; +use crate::{flipy, TileLike}; +#[derive(Debug, Clone)] +pub struct MbtTileRow { + pub zoom_level: u8, + pub tile_column: u32, + pub tile_row: u32, + pub tile_data: Vec, +} + +impl MbtTileRow { + #[must_use] + pub fn new( + zoom_level: u8, + tile_column: u32, + tile_row: u32, + tile_data: Vec, + ) -> Self { + Self { + zoom_level, + tile_column, + tile_row, + tile_data, + } + } +} + +impl TileLike for MbtTileRow { + fn new(x: u32, y: u32, z: u8) -> Self { + Self::new(z, x, y, vec![]) + } + + fn x(&self) -> u32 { + self.tile_column + } + + fn y(&self) -> u32 { + flipy(self.tile_row, self.zoom_level) + } + + fn z(&self) -> u8 { + self.zoom_level + } +} + +impl MbtTileRow { + #[must_use] + pub fn extension(&self) -> String { + tiletype_str(&self.tile_data) + } +} diff --git a/crates/utiles/src/parsing.rs b/crates/utiles/src/parsing.rs index f2633a80..6740f0eb 100644 --- a/crates/utiles/src/parsing.rs +++ b/crates/utiles/src/parsing.rs @@ -2,13 +2,11 @@ use crate::bbox::BBox; use crate::geojson::geojson_coords; use geo_types::Coord; use serde_json::Value; -use tracing::debug; pub fn parse_bbox_json(string: &str) -> serde_json::Result { // strip leading/trailing whitespace let s = string.trim(); // if the first char is "{" assume it is geojson-like - debug!("parse_bbox: {}", s); if s.starts_with('{') { // parse to serde_json::Value let v: Value = serde_json::from_str(s)?; @@ -22,7 +20,6 @@ pub fn parse_bbox_json(string: &str) -> serde_json::Result { let v: Value = serde_json::from_str(s)?; - debug!("{}", v); // Assume a single pair of coordinates represents a CoordTuple // and a four-element array represents a BBoxTuple let bbox = match v.as_array().map(std::vec::Vec::len) { @@ -36,7 +33,6 @@ pub fn parse_bbox_json(string: &str) -> serde_json::Result { } _ => panic!("Expected a two-element array or a four-element array"), }; - debug!("bbox: {:?}", bbox); bbox } @@ -44,12 +40,10 @@ pub fn parse_bbox(string: &str) -> Result> { // strip leading/trailing whitespace let s = string.trim(); // if the first char is "{" assume it is geojson-like - debug!("parse_bbox: {}", s); if s.starts_with('{') || s.starts_with('[') { return parse_bbox_json(s).map_err(std::convert::Into::into); } let parts: Vec = s.split(',').filter_map(|p| p.parse::().ok()).collect(); - if parts.len() == 4 { Ok(BBox::new(parts[0], parts[1], parts[2], parts[3])) } else { @@ -58,6 +52,14 @@ pub fn parse_bbox(string: &str) -> Result> { } } +pub fn parse_bbox_ext(string: &str) -> Result> { + // match 'world' or 'planet' + if string == "world" || string == "planet" { + return Ok(BBox::new(-180.0, -90.0, 180.0, 90.0)); + } + parse_bbox(string) +} + pub fn coords2bounds(mut coords: I) -> Option<(f64, f64, f64, f64)> where I: Iterator, diff --git a/crates/utiles/src/pmtiles/mod.rs b/crates/utiles/src/pmtiles/mod.rs new file mode 100644 index 00000000..e0c06ec7 --- /dev/null +++ b/crates/utiles/src/pmtiles/mod.rs @@ -0,0 +1,2 @@ +mod pmtile_id; +pub use pmtile_id::*; diff --git a/crates/utiles/src/pmtiles.rs b/crates/utiles/src/pmtiles/pmtile_id.rs similarity index 100% rename from crates/utiles/src/pmtiles.rs rename to crates/utiles/src/pmtiles/pmtile_id.rs diff --git a/crates/utiles/src/tile.rs b/crates/utiles/src/tile.rs index 10a26dae..69fe798a 100644 --- a/crates/utiles/src/tile.rs +++ b/crates/utiles/src/tile.rs @@ -1,21 +1,18 @@ -use serde::{Deserialize, Serialize}; -use serde_json::{Map, Value}; use std::cmp::Ordering; use std::error::Error; use std::str::FromStr; -use crate::utile; +use serde::{Deserialize, Serialize}; +use serde_json::{Map, Value}; -use crate::bbox::BBox; use crate::constants::EPSILON; -use crate::fns::{ - bounds, children, flipy, ll, lr, neighbors, parent, siblings, ul, ur, xy, -}; -use crate::lnglat::LngLat; +use crate::fns::{bounds, children, neighbors, parent, siblings, xy}; use crate::projection::Projection; use crate::tile_feature::TileFeature; -use crate::tile_tuple::XYZ; -use crate::{pmtiles, quadkey2tile, traits, xyz2quadkey}; +use crate::tile_like::TileLike; +use crate::tile_tuple::TileTuple; +use crate::utile; +use crate::{pmtiles, quadkey2tile, xyz2quadkey}; #[derive(Debug, Serialize, Deserialize)] pub struct TileFeatureGeometry { @@ -26,7 +23,8 @@ pub struct TileFeatureGeometry { #[derive(Debug, Serialize)] pub struct FeatureOptions { - pub fid: Option, // feature id + pub fid: Option, + // feature id pub props: Option>, pub projection: Projection, pub buffer: Option, @@ -52,36 +50,8 @@ pub struct Tile { pub z: u8, } -impl traits::Utiles for Tile { - fn ul(&self) -> LngLat { - ul(self.x, self.y, self.z) - } - - fn ur(&self) -> LngLat { - ur(self.x, self.y, self.z) - } - - fn lr(&self) -> LngLat { - lr(self.x, self.y, self.z) - } - - fn ll(&self) -> LngLat { - ll(self.x, self.y, self.z) - } - - fn bbox(&self) -> BBox { - let (west, south, east, north) = bounds(self.x, self.y, self.z); - BBox { - north, - south, - east, - west, - } - } -} - -impl From for Tile { - fn from(xyz: XYZ) -> Self { +impl From for Tile { + fn from(xyz: TileTuple) -> Self { Tile { x: xyz.0, y: xyz.1, @@ -140,38 +110,41 @@ impl FromStr for Tile { } } -impl Tile { - #[must_use] - pub fn new(x: u32, y: u32, z: u8) -> Self { - Tile { x, y, z } +impl TileLike for Tile { + fn new(x: u32, y: u32, z: u8) -> Self { + Self { x, y, z } } - #[allow(dead_code)] - #[must_use] - pub fn valid(&self) -> bool { - crate::fns::valid(self.x, self.y, self.z) - } - - #[must_use] - pub fn x(&self) -> u32 { + fn x(&self) -> u32 { self.x } - #[must_use] - pub fn y(&self) -> u32 { + fn y(&self) -> u32 { self.y } - #[must_use] - pub fn z(&self) -> u8 { + fn z(&self) -> u8 { self.z } +} +impl Tile { #[must_use] - pub fn zoom(&self) -> u8 { - self.z + pub fn new(x: u32, y: u32, z: u8) -> Self { + Tile { x, y, z } } + // #[allow(dead_code)] + // #[must_use] + // pub fn valid(&self) -> bool { + // crate::fns::valid(self.x, self.y, self.z) + // } + + // #[must_use] + // pub fn zoom(&self) -> u8 { + // self.z + // } + #[must_use] pub fn bounds(&self) -> (f64, f64, f64, f64) { bounds(self.x, self.y, self.z) @@ -188,7 +161,6 @@ impl Tile { Tile::new(x, y, z) } - #[must_use] pub fn from_pmid(id: u64) -> Result> { let (x, y, z) = pmtiles::pmid2xyz(id); Ok(Tile::new(x, y, z)) @@ -318,40 +290,40 @@ impl Tile { } } - #[must_use] - pub fn ul(&self) -> LngLat { - ul(self.x, self.y, self.z) - } - - #[must_use] - pub fn ll(&self) -> LngLat { - ll(self.x, self.y, self.z) - } - - #[must_use] - pub fn ur(&self) -> LngLat { - ur(self.x, self.y, self.z) - } - - #[must_use] - pub fn lr(&self) -> LngLat { - lr(self.x, self.y, self.z) - } - - #[must_use] - pub fn bbox(&self) -> (f64, f64, f64, f64) { - let ul = self.ul(); - let lr = self.lr(); - (ul.lng(), lr.lat(), lr.lng(), ul.lat()) - } - - #[must_use] - pub fn center(&self) -> LngLat { - let ul = self.ul(); - let lr = self.lr(); - LngLat::new((ul.lng() + lr.lng()) / 2.0, (ul.lat() + lr.lat()) / 2.0) - } - + // #[must_use] + // pub fn ul(&self) -> LngLat { + // ul(self.x, self.y, self.z) + // } + // + // #[must_use] + // pub fn ll(&self) -> LngLat { + // ll(self.x, self.y, self.z) + // } + // + // #[must_use] + // pub fn ur(&self) -> LngLat { + // ur(self.x, self.y, self.z) + // } + // + // #[must_use] + // pub fn lr(&self) -> LngLat { + // lr(self.x, self.y, self.z) + // } + + // #[must_use] + // pub fn bbox(&self) -> (f64, f64, f64, f64) { + // let ul = self.ul(); + // let lr = self.lr(); + // (ul.lng(), lr.lat(), lr.lng(), ul.lat()) + // } + // + // #[must_use] + // pub fn center(&self) -> LngLat { + // let ul = self.ul(); + // let lr = self.lr(); + // LngLat::new((ul.lng() + lr.lng()) / 2.0, (ul.lat() + lr.lat()) / 2.0) + // } + // #[must_use] pub fn up(&self) -> Self { Self { @@ -444,47 +416,47 @@ impl Tile { siblings(self.x, self.y, self.z) } - #[must_use] - pub fn sql_where(&self, flip: Option) -> String { - // classic mbtiles sqlite query: - // 'SELECT tile_data FROM tiles WHERE zoom_level = ? AND tile_column = ? AND tile_row = ?', - - // flip y for tms (default for mbtiles) - if flip.unwrap_or(true) { - format!( - "(zoom_level = {} AND tile_column = {} AND tile_row = {})", - self.z, - self.x, - flipy(self.y, self.z) - ) - } else { - format!( - "(zoom_level = {} AND tile_column = {} AND tile_row = {})", - self.z, self.x, self.y - ) - } - } - - #[must_use] - pub fn json_arr_min(&self) -> String { - format!("[{},{},{}]", self.x, self.y, self.z) - } - - #[must_use] - pub fn json_arr(&self) -> String { - format!("[{}, {}, {}]", self.x, self.y, self.z) - } - - #[must_use] - pub fn json_obj(&self) -> String { - serde_json::to_string(self).unwrap() - } - - #[must_use] - pub fn tuple_string(&self) -> String { - format!("({}, {}, {})", self.x, self.y, self.z) - } - + // #[must_use] + // pub fn sql_where(&self, flip: Option) -> String { + // // classic mbtiles sqlite query: + // // 'SELECT tile_data FROM tiles WHERE zoom_level = ? AND tile_column = ? AND tile_row = ?', + // + // // flip y for tms (default for mbtiles) + // if flip.unwrap_or(true) { + // format!( + // "(zoom_level = {} AND tile_column = {} AND tile_row = {})", + // self.z, + // self.x, + // flipy(self.y, self.z) + // ) + // } else { + // format!( + // "(zoom_level = {} AND tile_column = {} AND tile_row = {})", + // self.z, self.x, self.y + // ) + // } + // } + + // #[must_use] + // pub fn json_arr_min(&self) -> String { + // format!("[{},{},{}]", self.x, self.y, self.z) + // } + // + // #[must_use] + // pub fn json_arr(&self) -> String { + // format!("[{}, {}, {}]", self.x, self.y, self.z) + // } + // + // #[must_use] + // pub fn json_obj(&self) -> String { + // serde_json::to_string(self).unwrap() + // } + // + // #[must_use] + // pub fn tuple_string(&self) -> String { + // format!("({}, {}, {})", self.x, self.y, self.z) + // } + // pub fn feature( &self, opts: &FeatureOptions, @@ -558,7 +530,7 @@ impl Tile { impl From<(u32, u32, u8)> for Tile { fn from(tuple: (u32, u32, u8)) -> Self { - XYZ::from(tuple).into() + TileTuple::from(tuple).into() } } @@ -584,20 +556,10 @@ impl From<&Vec> for Tile { Tile::from((x, y, z)) } } + impl From> for Tile { fn from(arr: Vec) -> Self { Tile::from(&arr) - // - // if arr.len() < 3 { - // panic!( - // "Invalid json value: {}", - // serde_json::to_string(&arr).unwrap() - // ); - // } - // let x = arr[0].as_u64().unwrap() as u32; - // let y = arr[1].as_u64().unwrap() as u32; - // let z = arr[2].as_u64().unwrap() as u8; - // Tile::from((x, y, z)) } } @@ -612,8 +574,6 @@ impl From<&Value> for Tile { serde_json::to_string(&v).unwrap() ); Tile::from(v) - // let tuple = serde_json::from_value::(val).unwrap(); - // return Tile::from(tuple); } Value::Object(v) => { // if it has a "tile" key, use that @@ -623,7 +583,7 @@ impl From<&Value> for Tile { && v["tile"].as_array().unwrap().len() == 3 { let tuple = - serde_json::from_value::(v["tile"].clone()).unwrap(); + serde_json::from_value::(v["tile"].clone()).unwrap(); return Tile::from(tuple); } Tile::from(v) @@ -647,6 +607,12 @@ impl From<&str> for Tile { } } +impl From for (u32, u32, u8) { + fn from(tile: Tile) -> Self { + (tile.x, tile.y, tile.z) + } +} + #[cfg(test)] mod tests { use super::*; @@ -687,6 +653,7 @@ mod tests { let tile_from_arr = Tile::from(val_arr); assert_eq!(tile_from_arr, Tile::new(1, 2, 3)); } + #[test] fn tile_from_value_obj_with_array() { let json_obj_with_tile_array = r#"{"tile": [1, 2, 3]}"#; @@ -696,9 +663,3 @@ mod tests { assert_eq!(tile_from_obj_with_tile_array, Tile::new(1, 2, 3)); } } - -impl From for (u32, u32, u8) { - fn from(tile: Tile) -> Self { - (tile.x, tile.y, tile.z) - } -} diff --git a/crates/utiles/src/tile_data_row.rs b/crates/utiles/src/tile_data_row.rs new file mode 100644 index 00000000..8711e6c2 --- /dev/null +++ b/crates/utiles/src/tile_data_row.rs @@ -0,0 +1,7 @@ +use crate::tile::Tile; + +#[derive(Debug)] +pub struct TileData { + pub xyz: Tile, + pub data: Vec, +} diff --git a/crates/utiles/src/tile_like.rs b/crates/utiles/src/tile_like.rs new file mode 100644 index 00000000..f58d3f1a --- /dev/null +++ b/crates/utiles/src/tile_like.rs @@ -0,0 +1,141 @@ +use crate::{flipy, pmtiles, LngLat, Tile}; + +pub trait TileLike { + #[must_use] + fn new(x: u32, y: u32, z: u8) -> Self; + + fn x(&self) -> u32; + fn y(&self) -> u32; + fn z(&self) -> u8; + + #[must_use] + fn zoom(&self) -> u8 { + self.z() + } + + fn yflip(&self) -> u32 { + flipy(self.y(), self.z()) + } + + #[must_use] + fn tile(&self) -> Tile { + Tile::new(self.x(), self.y(), self.z()) + } + + /// both bc I keep forgetting which is which + fn flipy(&self) -> u32 { + flipy(self.y(), self.z()) + } + + #[must_use] + fn valid(&self) -> bool { + crate::valid(self.x(), self.y(), self.z()) + } + + #[must_use] + fn ul(&self) -> LngLat { + crate::ul(self.x(), self.y(), self.z()) + } + + #[must_use] + fn ur(&self) -> LngLat { + crate::ul(self.x() + 1, self.y(), self.z()) + } + + #[must_use] + fn lr(&self) -> LngLat { + crate::ul(self.x() + 1, self.y() + 1, self.z()) + } + + #[must_use] + fn ll(&self) -> LngLat { + crate::ul(self.x(), self.y() + 1, self.z()) + } + + #[must_use] + fn quadkey(&self) -> String { + crate::xyz2quadkey(self.x(), self.y(), self.z()) + } + + #[must_use] + fn qk(&self) -> String { + crate::xyz2quadkey(self.x(), self.y(), self.z()) + } + + #[must_use] + fn pmtileid(&self) -> u64 { + pmtiles::xyz2pmid(self.x(), self.y(), self.z()) + } + + #[must_use] + fn pmid(&self) -> u64 { + self.pmtileid() + } + + #[must_use] + fn bbox(&self) -> (f64, f64, f64, f64) { + let ul = self.ul(); + let lr = self.lr(); + (ul.lng(), lr.lat(), lr.lng(), ul.lat()) + } + + #[must_use] + fn center(&self) -> LngLat { + let ul = self.ul(); + let lr = self.lr(); + LngLat::new((ul.lng() + lr.lng()) / 2.0, (ul.lat() + lr.lat()) / 2.0) + } + + #[must_use] + fn json_arr(&self) -> String { + format!("[{}, {}, {}]", self.x(), self.y(), self.z()) + } + + #[must_use] + fn json_arr_min(&self) -> String { + format!("[{},{},{}]", self.x(), self.y(), self.z()) + } + + #[must_use] + fn json(&self) -> String { + format!( + "{{\"x\":{}, \"y\":{}, \"z\":{}}}", + self.x(), + self.y(), + self.z() + ) + } + + #[must_use] + fn json_obj(&self) -> String { + self.tile().json_obj() + } + + #[must_use] + fn tuple_string(&self) -> String { + format!("({}, {}, {})", self.x(), self.y(), self.z()) + } + + #[must_use] + fn sql_where(&self, flip: Option) -> String { + // classic mbtiles sqlite query: + // 'SELECT tile_data FROM tiles WHERE zoom_level = ? AND tile_column = ? AND tile_row = ?', + + // flip y for tms (default for mbtiles) + if flip.unwrap_or(true) { + format!( + "(zoom_level = {} AND tile_column = {} AND tile_row = {})", + self.z(), + self.x(), + flipy(self.y(), self.z()) + ) + } else { + format!( + "(zoom_level = {} AND tile_column = {} AND tile_row = {})", + self.z(), + self.x(), + self.y() + ) + } + } +} diff --git a/crates/utiles/src/tile_tuple.rs b/crates/utiles/src/tile_tuple.rs index 3fbf2b87..7fb7f142 100644 --- a/crates/utiles/src/tile_tuple.rs +++ b/crates/utiles/src/tile_tuple.rs @@ -1,11 +1,30 @@ +use crate::tile_like::TileLike; use serde::Deserialize; - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize)] #[allow(clippy::upper_case_acronyms)] -pub struct XYZ(pub u32, pub u32, pub u8); +pub struct TileTuple(pub u32, pub u32, pub u8); -impl From<(u32, u32, u8)> for XYZ { +impl From<(u32, u32, u8)> for TileTuple { fn from(xyz: (u32, u32, u8)) -> Self { - XYZ(xyz.0, xyz.1, xyz.2) + TileTuple(xyz.0, xyz.1, xyz.2) + } +} + +impl TileLike for TileTuple { + #[must_use] + fn new(x: u32, y: u32, z: u8) -> Self { + Self(x, y, z) + } + + fn x(&self) -> u32 { + self.0 + } + + fn y(&self) -> u32 { + self.1 + } + + fn z(&self) -> u8 { + self.2 } } diff --git a/crates/utiles/src/tilecrz.rs b/crates/utiles/src/tilecrz.rs new file mode 100644 index 00000000..50a643e9 --- /dev/null +++ b/crates/utiles/src/tilecrz.rs @@ -0,0 +1,40 @@ +use crate::fns::flipy; +use crate::tile_like::TileLike; + +#[derive(Debug)] +struct TileCrz { + // column -> x + tile_column: u32, + // row -> y + tile_row: u32, + // zoom_level -> z + zoom_level: u8, +} + +impl TileCrz { + pub fn new(tile_column: u32, tile_row: u32, zoom_level: u8) -> Self { + Self { + tile_column, + tile_row, + zoom_level, + } + } +} + +impl TileLike for TileCrz { + fn new(x: u32, y: u32, z: u8) -> Self { + Self::new(x, flipy(y, z), z) + } + + fn x(&self) -> u32 { + self.tile_column + } + + fn y(&self) -> u32 { + flipy(self.tile_row, self.zoom_level) + } + + fn z(&self) -> u8 { + self.zoom_level + } +} diff --git a/crates/utiles/src/traits.rs b/crates/utiles/src/traits.rs index c1301851..85753d72 100644 --- a/crates/utiles/src/traits.rs +++ b/crates/utiles/src/traits.rs @@ -23,7 +23,7 @@ pub trait TGeoBbox { } pub trait Utiles { - fn ul(&self) -> TLngLat; + // fn ul(&self) -> TLngLat; fn ur(&self) -> TLngLat; fn lr(&self) -> TLngLat; fn ll(&self) -> TLngLat; diff --git a/crates/utiles/src/zoom.rs b/crates/utiles/src/zoom.rs index 55356a21..ec40843e 100644 --- a/crates/utiles/src/zoom.rs +++ b/crates/utiles/src/zoom.rs @@ -1,8 +1,62 @@ +type Zooms = Vec; +type ZoomsSetInt = u32; + +pub struct ZoomRange { + pub minz: u8, + pub maxz: u8, +} + +// default zoom range +impl Default for ZoomRange { + fn default() -> Self { + Self { minz: 0, maxz: 32 } + } +} + +impl ZoomRange { + #[must_use] + pub fn new(min: u8, max: u8) -> Self { + Self { + minz: min, + maxz: max, + } + } + + #[must_use] + pub fn from_max(max: u8) -> Self { + Self { minz: 0, maxz: max } + } + + #[must_use] + pub fn from_min(min: u8) -> Self { + Self { + minz: min, + maxz: 32, + } + } +} + +#[must_use] +pub fn zset2zvec(zset: ZoomsSetInt) -> Vec { + (0..32) + .rev() + .filter(|&i| (zset & (1 << i)) != 0) + .map(|i| (31 - i) as u8) // Convert bit index to zoom level and cast to u8 + .collect() +} + +#[must_use] +pub fn zvec2zset(zvec: Zooms) -> ZoomsSetInt { + zvec.iter().fold(0, |acc, &z| acc | (1 << (31 - z))) +} + pub enum ZoomOrZooms { Zoom(u8), Zooms(Vec), } +pub struct ZoomsSet(ZoomsSetInt); + impl From for ZoomOrZooms { fn from(zoom: u8) -> Self { ZoomOrZooms::Zoom(zoom) @@ -14,3 +68,82 @@ impl From> for ZoomOrZooms { ZoomOrZooms::Zooms(zooms) } } + +impl From for Zooms { + fn from(zoom_or_zooms: ZoomOrZooms) -> Self { + match zoom_or_zooms { + ZoomOrZooms::Zoom(zoom) => vec![zoom], + ZoomOrZooms::Zooms(zooms) => zooms, + } + } +} + +impl From for ZoomsSetInt { + fn from(zoom_or_zooms: ZoomOrZooms) -> Self { + match zoom_or_zooms { + ZoomOrZooms::Zoom(zoom) => 1 << (31 - zoom), + ZoomOrZooms::Zooms(zooms) => zvec2zset(zooms), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn zset2zvec_none() { + let zset: u32 = 0b00000000_00000000_00000000_00000000; // Example, zoom levels 2 and 4 are set + let zvec: Vec = vec![]; + assert_eq!(zset2zvec(zset), zvec); + } + #[test] + fn zset2zvec_0_1_2() { + let zset: u32 = 0b11100000_00000000_00000000_00000000; // Example, zoom levels 2 and 4 are set + let zvec: Vec = vec![0, 1, 2]; + + assert_eq!(zset2zvec(zset), zvec); + } + #[test] + fn zset2zvec_all() { + let zset: u32 = 0b11111111_11111111_11111111_11111111; // Example, zoom levels 2 and 4 are set + let zvec: Vec = vec![ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + ]; + assert_eq!(zset2zvec(zset), zvec); + } + + #[test] + fn zvec2zset_none() { + let zset: u32 = 0b00000000_00000000_00000000_00000000; // Example, zoom levels 2 and 4 are set + let zvec: Vec = vec![]; + assert_eq!(zvec2zset(zvec), zset); + } + + #[test] + fn zvec2zset_0_1_2() { + let zset: u32 = 0b11100000_00000000_00000000_00000000; // Example, zoom levels 2 and 4 are set + let zvec: Vec = vec![0, 1, 2]; + + assert_eq!(zvec2zset(zvec), zset); + } + + #[test] + fn zvec2zset_all() { + let zset: u32 = 0b11111111_11111111_11111111_11111111; // Example, zoom levels 2 and 4 are set + let zvec: Vec = vec![ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + ]; + assert_eq!(zvec2zset(zvec), zset); + } + + #[test] + fn zvec2zset_0_1_2_3_4_5_6_7() { + let zset: u32 = 0b11111111_00000000_00000000_00000000; // Example, zoom levels 2 and 4 are set + let zvec: Vec = vec![0, 1, 2, 3, 4, 5, 6, 7]; + let zset_from_zvec = zvec2zset(zvec); + assert_eq!(zset_from_zvec, zset); + } +} diff --git a/crates/utilesqlite/Cargo.lock b/crates/utilesqlite/Cargo.lock deleted file mode 100644 index 6464e641..00000000 --- a/crates/utilesqlite/Cargo.lock +++ /dev/null @@ -1,741 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "fallible-iterator" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" - -[[package]] -name = "fallible-streaming-iterator" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" - -[[package]] -name = "fast_hilbert" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ec2bbe15af87954c739e236021f4411766c0f2b9c4a5f0b9317bcf6048ebf8" -dependencies = [ - "num-traits", -] - -[[package]] -name = "geo-types" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9705398c5c7b26132e74513f4ee7c1d7dafd786004991b375c172be2be0eecaa" -dependencies = [ - "approx", - "num-traits", - "serde", -] - -[[package]] -name = "geojson" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d728c1df1fbf328d74151efe6cb0586f79ee813346ea981add69bd22c9241b" -dependencies = [ - "geo-types", - "log", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "gimli" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" - -[[package]] -name = "hashbrown" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" -dependencies = [ - "ahash", - "allocator-api2", -] - -[[package]] -name = "hashlink" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" -dependencies = [ - "hashbrown", -] - -[[package]] -name = "hermit-abi" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "libc" -version = "0.2.150" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "libsqlite3-sys" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" -dependencies = [ - "libc", - "wasi", - "windows-sys", -] - -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "proc-macro2" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "rusqlite" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" -dependencies = [ - "bitflags 2.4.1", - "fallible-iterator", - "fallible-streaming-iterator", - "hashlink", - "libsqlite3-sys", - "smallvec", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "serde" -version = "1.0.192" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.192" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "serde_json" -version = "1.0.108" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_tuple" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f025b91216f15a2a32aa39669329a475733590a015835d1783549a56d09427" -dependencies = [ - "serde", - "serde_tuple_macros", -] - -[[package]] -name = "serde_tuple_macros" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4076151d1a2b688e25aaf236997933c66e18b870d0369f8b248b8ab2be630d7e" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "smallvec" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" - -[[package]] -name = "socket2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "tilejson" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a16212e5ea60f2b406835981338a1df9b206fab312e3470502d60f69e590a9c9" -dependencies = [ - "serde", - "serde_json", - "serde_tuple", -] - -[[package]] -name = "tokio" -version = "1.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys", -] - -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "tokio-rusqlite" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aa66395f5ff117faee90c9458232c936405f9227ad902038000b74b3bc1feac" -dependencies = [ - "crossbeam-channel", - "rusqlite", - "tokio", -] - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "utiles" -version = "0.0.1" -dependencies = [ - "anyhow", - "fast_hilbert", - "geo-types", - "geojson", - "serde", - "serde_json", - "thiserror", - "tilejson", - "tracing", -] - -[[package]] -name = "utilesqlite" -version = "0.1.0" -dependencies = [ - "rusqlite", - "serde", - "serde_json", - "tilejson", - "tokio", - "tokio-rusqlite", - "tracing", - "utiles", -] - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "zerocopy" -version = "0.7.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] diff --git a/crates/utilesqlite/Cargo.toml b/crates/utilesqlite/Cargo.toml index b652d297..e747bb0d 100644 --- a/crates/utilesqlite/Cargo.toml +++ b/crates/utilesqlite/Cargo.toml @@ -14,6 +14,8 @@ name = "utilesql" path = "src/bin.rs" [dependencies] +deadpool-sqlite = { version = "0.7.0", features = ["tracing"] } +#async-sqlite = { version = "0.1.0", features = ["bundled", "backup", "blob", "serde_json", "trace", "hooks", "array", "functions", "modern-full"] } rusqlite = { workspace = true, features = ["bundled", "vtab", "blob", "backup", "functions", ] } serde.workspace = true serde_json.workspace = true diff --git a/crates/utilesqlite/src/lib.rs b/crates/utilesqlite/src/lib.rs index f6c4085a..3cc8e483 100644 --- a/crates/utilesqlite/src/lib.rs +++ b/crates/utilesqlite/src/lib.rs @@ -1,2 +1,6 @@ pub mod mbtiles; +pub mod mbtiles_async; pub mod squealite; + +pub use mbtiles::Mbtiles; +pub use mbtiles_async::MbtilesAsync; diff --git a/crates/utilesqlite/src/mbtiles.rs b/crates/utilesqlite/src/mbtiles.rs index e45b6696..6738c79f 100644 --- a/crates/utilesqlite/src/mbtiles.rs +++ b/crates/utilesqlite/src/mbtiles.rs @@ -17,6 +17,10 @@ impl Mbtiles { Mbtiles { conn } } + pub fn conn(&self) -> &Connection { + &self.conn + } + pub fn metadata(&self) -> RusqliteResult> { mbtiles_metadata(&self.conn) } @@ -103,7 +107,7 @@ impl From<&Path> for Mbtiles { } pub fn mbtiles_metadata(conn: &Connection) -> RusqliteResult> { - let mut stmt = conn.prepare("SELECT name, value FROM metadata")?; + let mut stmt = conn.prepare_cached("SELECT name, value FROM metadata")?; let mdata = stmt .query_map([], |row| { Ok(MbtilesMetadataRow { @@ -130,7 +134,7 @@ pub fn has_unique_index_on_metadata(conn: &Connection) -> RusqliteResult { pub fn zoom_levels(conn: &Connection) -> RusqliteResult> { let mut stmt = conn.prepare("SELECT DISTINCT zoom_level FROM tiles")?; let zoom_levels = stmt - .query_map([], |row| Ok(row.get(0)?))? + .query_map([], |row| row.get(0))? .collect::, rusqlite::Error>>()?; Ok(zoom_levels) } @@ -159,34 +163,47 @@ pub fn has_tiles_table_or_view(connection: &Connection) -> RusqliteResult } pub fn has_tiles_view(connection: &Connection) -> RusqliteResult { - let mut stmt = connection - .prepare("SELECT name FROM sqlite_master WHERE type='view' AND name='tiles'")?; - let nrows = stmt.query([]).iter().count(); - Ok(nrows == 1) + let mut stmt = connection.prepare( + "SELECT COUNT(name) FROM sqlite_master WHERE type='view' AND name='tiles'", + )?; + let nrows = stmt.query_row([], |row| { + let count: i64 = row.get(0)?; + Ok(count) + })?; + Ok(nrows == 1_i64) } pub fn has_tiles_table(connection: &Connection) -> RusqliteResult { let mut stmt = connection.prepare( - "SELECT name FROM sqlite_master WHERE type='table' AND name='tiles'", + "SELECT COUNT(name) FROM sqlite_master WHERE type='table' AND name='tiles'", )?; - let nrows = stmt.query([]).iter().count(); - Ok(nrows == 1) + let nrows = stmt.query_row([], |row| { + let count: i64 = row.get(0)?; + Ok(count) + })?; + Ok(nrows == 1_i64) } pub fn has_metadata_table(connection: &Connection) -> RusqliteResult { let mut stmt = connection.prepare( - "SELECT name FROM sqlite_master WHERE type='table' AND name='metadata'", + "SELECT COUNT(name) FROM sqlite_master WHERE type='table' AND name='metadata'", )?; - let nrows = stmt.query([]).iter().count(); - Ok(nrows == 1) + let nrows = stmt.query_row([], |row| { + let count: i64 = row.get(0)?; + Ok(count) + })?; + Ok(nrows == 1_i64) } pub fn has_metadata_view(connection: &Connection) -> RusqliteResult { let mut stmt = connection.prepare( - "SELECT name FROM sqlite_master WHERE type='view' AND name='metadata'", + "SELECT COUNT(name) FROM sqlite_master WHERE type='view' AND name='metadata'", )?; - let nrows = stmt.query([]).iter().count(); - Ok(nrows == 1) + let nrows = stmt.query_row([], |row| { + let count: i64 = row.get(0)?; + Ok(count) + })?; + Ok(nrows == 1_i64) } pub fn has_metadata_table_or_view(connection: &Connection) -> RusqliteResult { diff --git a/crates/utilesqlite/src/mbtiles_async.rs b/crates/utilesqlite/src/mbtiles_async.rs new file mode 100644 index 00000000..456a89f1 --- /dev/null +++ b/crates/utilesqlite/src/mbtiles_async.rs @@ -0,0 +1,61 @@ +use std::error::Error; + +use deadpool_sqlite::{self, Config, Pool, PoolError, Runtime}; +use tilejson::TileJSON; +use tracing::error; + +use utiles::mbtiles::metadata2tilejson; +use utiles::mbtiles::metadata_row::MbtilesMetadataRow; + +use crate::mbtiles::mbtiles_metadata; + +pub struct MbtilesAsync { + // pub client: Client, + pub pool: Pool, +} + +impl MbtilesAsync { + pub async fn open(path: &str) -> Result { + let cfg = Config::new(path); + let pool = cfg.create_pool(Runtime::Tokio1).unwrap(); + // let conn = pool.get().await.unwrap(); + // let conn = pool.get().await; + + // pool.status() + + // .expect("DB connection failed"); + Ok(Self { pool }) + // let c = ClientBuilder::new().path(path).open().await?; + // Ok(Self { client: c }) + } + + pub async fn metadata_rows( + &self, + ) -> Result, Box> { + let c = self.pool.get().await.unwrap(); + let r = c + .interact(|conn| { + mbtiles_metadata(conn) + // let mdrows = mbtiles_metadata(conn); + // mdrows + }) + .await; + + // let mdrows = self.client.conn(|conn| mbtiles_metadata(conn)).await?; + // println!("mdrows: {:?}", mdrows); + // Ok(vec![]) + Ok(r??) + } + + pub async fn tilejson(&self) -> Result> { + let metadata = self.metadata_rows().await?; + let tj = metadata2tilejson(metadata); + match tj { + Ok(t) => Ok(t), + Err(e) => { + error!("Error parsing metadata to TileJSON: {}", e); + Err(e) + } + } + } +} diff --git a/pyproject.toml b/pyproject.toml index 63753e30..5ca3005a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,7 @@ testpaths = [ ] addopts = [ "--doctest-modules", + "--benchmark-skip", "-v" ] markers = [ @@ -145,6 +146,7 @@ ban-relative-imports = "all" [tool.ruff.per-file-ignores] # Tests can use magic values, assertions, and relative imports "tests/**/*" = ["PLR2004", "S101", "TID252"] +"bench/**/*" = ["PLR2004", "S101", "TID252"] [tool.ruff.pydocstyle] convention = "google" diff --git a/python/utiles/__init__.py b/python/utiles/__init__.py index 587d44b1..a050be15 100644 --- a/python/utiles/__init__.py +++ b/python/utiles/__init__.py @@ -1,8 +1,7 @@ """utiles""" from __future__ import annotations -import math -from typing import List, Sequence, Tuple, Union +from typing import Sequence, Tuple, Union from utiles._utiles import ( TILETYPE_GIF, @@ -30,6 +29,7 @@ from_pmtileid, from_tuple, geojson_bounds, + geotransform2optzoom, lnglat, minmax, neighbors, @@ -37,6 +37,8 @@ parse_tile_arg, parse_tiles, pmtileid, + pmtileid2xyz, + qk2xyz, quadkey, quadkey2xyz, quadkey_to_tile, @@ -44,8 +46,6 @@ tile, tiles, tiles_count, - qk2xyz, - pmtileid2xyz, tiles_list, tiletype, tiletype2headers, @@ -90,6 +90,7 @@ "from_pmtileid", "from_tuple", "geojson_bounds", + "geotransform2optzoom", "lnglat", "minmax", "neighbors", @@ -118,50 +119,3 @@ "xyz", "xyz2quadkey", ) - - -def optzoom( - geo_transform: Union[ - Tuple[float, float, float, float, float, float], - List[float], - ], - pixel_size: int = 256, -) -> int: - """Return the optimal zoom level for a given geo_transform - - Args: - geo_transform (Sequence[float]): Geo transform array - - Returns: - int: Optimal zoom level - - Example: - >>> gt = [-77.000138, 0.000278, 0.0, 26.0001389, 0.0, -0.000278] - >>> optzoom(gt) - 12 - - """ - degrees_per_pixel = geo_transform[1] - equator = 2 * math.pi * 6378137 # 2 * pi * radius of earth in meters - resolution = degrees_per_pixel * (equator / 360) - zoom_level = math.log((equator / pixel_size) / resolution, 2) - return min(math.floor(zoom_level), 20) - - -def tiletile_str(n: int) -> str: - if n == TILETYPE_PNG: - return "png" - elif n == TILETYPE_JPG: - return "jpg" - elif n == TILETYPE_GIF: - return "gif" - elif n == TILETYPE_WEBP: - return "webp" - elif n == TILETYPE_PBF: - return "pbf" - elif n == TILETYPE_PBFGZ: - return "pbfgz" - elif n == TILETYPE_JSON: - return "json" - else: - return "unknown" diff --git a/python/utiles/_click.py b/python/utiles/_click.py index 5729c3fb..559846e8 100644 --- a/python/utiles/_click.py +++ b/python/utiles/_click.py @@ -17,7 +17,7 @@ def get_help_option(self, _ctx: click.Context) -> None: # The CLI command group. -def _click_cli(name: str) -> NoHelpCommand: +def _click_cli(name: str) -> click.Command: @click.command( name=name, cls=NoHelpCommand, diff --git a/python/utiles/_utiles.pyi b/python/utiles/_utiles.pyi index b8a8a09e..6178fcda 100644 --- a/python/utiles/_utiles.pyi +++ b/python/utiles/_utiles.pyi @@ -236,6 +236,9 @@ def _coords(obj: Any) -> Iterable[Tuple[float, float]]: ... def geojson_bounds(obj: Any) -> LngLatBbox: ... def pmtileid(*tile: TileLike) -> int: ... def from_pmtileid(pmtileid: int) -> Tile: ... +def geotransform2optzoom( + geotransform: Tuple[float, float, float, float, float, float] +) -> int: ... # CLI def ut_cli(args: list[str]) -> None: ... diff --git a/python/utiles/dev/__init__.py b/python/utiles/dev/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/python/utiles/dev/testing.py b/python/utiles/dev/testing.py new file mode 100644 index 00000000..570a8188 --- /dev/null +++ b/python/utiles/dev/testing.py @@ -0,0 +1,92 @@ +"""Utiles rust cli tests""" +from __future__ import annotations + +try: + from orjson import loads as json_loads +except ImportError: + from json import loads as json_loads + +import sys +from dataclasses import dataclass +from subprocess import CompletedProcess, run +from time import time_ns +from typing import Any + + +@dataclass +class CliResult: + """CLI result""" + + __slots__ = ( + "args", + "stdout", + "stderr", + "returncode", + "dt", + "input", + "completed_process", + ) + + args: list[str] + stdout: str + stderr: str + returncode: int + + # time in seconds + dt: float + # input + input: str | None + completed_process: CompletedProcess[str] | None + + def __str__(self) -> str: + fields = ( + "args", + "stdout", + "stderr", + "returncode", + "dt", + "input", + ) + parts = (f"{f}={getattr(self, f)}" for f in fields) + return f"CliResult({', '.join(parts)})" + + @property + def exit_code(self) -> int: + """Exit code""" + return self.returncode + + @property + def output(self) -> str: + """Success""" + return self.stdout + + @property + def parse_json(self) -> Any: + """Parse json""" + return json_loads(self.stdout) + + +def run_cli( + args: list[str] | None, + input: str | None = None, +) -> CliResult: + _python = sys.executable + _args = args or [] + ti = time_ns() + completed_process = run( + [_python, "-m", "utiles.cli", *_args], + input=input, + capture_output=True, + text=True, + shell=False, # noqa: S603 + ) + tf = time_ns() + return CliResult( + args=_args, + stdout=completed_process.stdout, + stderr=completed_process.stderr, + returncode=completed_process.returncode, + input=input, + dt=(tf - ti) / 1e9, + completed_process=completed_process, + ) diff --git a/src/lib.rs b/src/lib.rs index e1e0484e..c79dc6b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,13 @@ +#![deny(clippy::all)] +#![deny(clippy::perf)] +#![warn(clippy::style)] +// #![warn(clippy::pedantic)] +#![warn(clippy::unnecessary_wraps)] +#![allow(clippy::module_name_repetitions)] +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::similar_names)] +#![allow(clippy::too_many_lines)] use self::pyutiles::pytilelike::PyTileLike; use self::pyutiles::zoom::PyZoomOrZooms; use pyo3::exceptions::{self, PyValueError}; @@ -14,6 +24,7 @@ use utiles::libtiletype; use utiles::zoom::ZoomOrZooms; mod cli; +mod pyfns; mod pyutiles; #[derive(FromPyObject)] @@ -40,7 +51,7 @@ impl From for BBox { #[pyfunction] fn minmax(zoom: i32) -> PyResult<(u32, u32)> { if !(0..=32).contains(&zoom) { - return Err(PyErr::new::(format!( + Err(PyErr::new::(format!( "zoom must be between 0 and 32: {zoom}" )))?; } @@ -83,8 +94,7 @@ fn tiletype_str(buffer: &[u8]) -> String { #[pyfunction] fn tiletype2headers(tiletype: usize) -> Vec<(&'static str, &'static str)> { - let headers = libtiletype::headers(&libtiletype::const2enum(tiletype)); - headers + libtiletype::headers(&libtiletype::const2enum(tiletype)) } #[pyfunction] @@ -203,59 +213,13 @@ fn parse_tiles(args: &PyTuple) -> PyResult> { #[pyfunction] #[pyo3(signature = (* args))] -fn _parse_tile_arg(args: &PyTuple) -> PyResult { +pub fn _parse_tile_arg(args: &PyTuple) -> PyResult { parse_tile_arg(args) } #[pyfunction] #[pyo3(signature = (* args))] -fn ul(args: &PyTuple) -> PyResult { - let tile = parse_tile_arg(args)?; - let lnglat = tile.ul(); - Ok(lnglat) -} - -#[pyfunction] -fn xy(lng: f64, lat: f64, truncate: Option) -> PyResult<(f64, f64)> { - let xy = utiles::xy(lng, lat, truncate); - Ok(xy) -} - -#[pyfunction] -fn _xy(lng: f64, lat: f64, truncate: Option) -> PyResult<(f64, f64)> { - let trunc = truncate.unwrap_or(false); - if !trunc && (lat <= -90.0 || lat >= 90.0) { - return Err(PyErr::new::(format!( - "Invalid latitude: {lat}" - )))?; - } - let xy = utiles::_xy(lng, lat, truncate); - match xy { - Ok(xy) => Ok(xy), - Err(_e) => Err(PyErr::new::(format!( - "Invalid latitude: {lat}" - )))?, - } -} - -#[pyfunction] -fn lnglat(x: f64, y: f64, truncate: Option) -> PyResult { - // let trunc = truncate.unwrap_or(false); - let lnglat = utiles::lnglat(x, y, truncate); - Ok(PyLngLat::new(lnglat.lng(), lnglat.lat())) -} - -#[pyfunction] -#[pyo3(signature = (* args))] -fn bounds(args: &PyTuple) -> PyResult { - let tile = parse_tile_arg(args)?; - let bbox = tile.bounds(); - Ok(bbox) -} - -#[pyfunction] -#[pyo3(signature = (* args))] -fn xy_bounds(args: &PyTuple) -> PyResult { +pub fn xy_bounds(args: &PyTuple) -> PyResult { let tile = parse_tile_arg(args)?; let pybbox = utiles::xyz2bbox(tile.xyz.x, tile.xyz.y, tile.xyz.z); Ok(PyBbox::new( @@ -267,9 +231,9 @@ fn xy_bounds(args: &PyTuple) -> PyResult { } #[pyfunction] -fn tile(lng: f64, lat: f64, zoom: u8, truncate: Option) -> PyResult { +pub fn tile(lng: f64, lat: f64, zoom: u8, truncate: Option) -> PyResult { if lat <= -90.0 || lat >= 90.0 { - return Err(PyErr::new::(format!( + Err(PyErr::new::(format!( "Invalid latitude: {lat}" )))?; } @@ -285,15 +249,15 @@ fn pmtileid(args: &PyTuple) -> PyResult { } #[pyfunction] -fn pmtileid2xyz(pmtileid: u64) -> PyResult { +fn pmtileid2xyz(pmtileid: u64) -> PyTile { let xyz = utiles::Tile::from_pmtileid(pmtileid); - Ok(PyTile::from(xyz)) + PyTile::from(xyz) } #[pyfunction] -fn from_pmtileid(pmtileid: u64) -> PyResult { +fn from_pmtileid(pmtileid: u64) -> PyTile { let xyz = utiles::Tile::from_pmtileid(pmtileid); - Ok(PyTile::from(xyz)) + PyTile::from(xyz) } #[pyfunction] @@ -329,7 +293,7 @@ fn parent(args: &PyTuple, zoom: Option) -> PyResult> { // Check that the zoom level is valid if zoom >= tile.xyz.z { - return Err(PyErr::new::(format!( + Err(PyErr::new::(format!( "zoom level {} is invalid for tile with zoom {}", zoom, tile.xyz.z )))?; @@ -351,7 +315,7 @@ fn children(args: &PyTuple, zoom: Option) -> PyResult> { let tile = parse_tile_arg(args)?; let zoom = zoom.unwrap_or(tile.xyz.z + 1); if zoom < tile.xyz.z { - return Err(PyErr::new::(format!( + Err(PyErr::new::(format!( "zoom must be greater than or equal to tile zoom: {}", tile.xyz.z )))?; @@ -366,7 +330,7 @@ fn neighbors(args: &PyTuple, zoom: Option) -> PyResult> { let tile = parse_tile_arg(args)?; let zoom = zoom.unwrap_or(tile.xyz.z); if zoom < tile.xyz.z { - return Err(PyErr::new::(format!( + Err(PyErr::new::(format!( "zoom must be greater than or equal to tile zoom: {}", tile.xyz.z )))?; @@ -387,10 +351,10 @@ fn bounding_tile(args: &PyTuple, truncate: Option) -> PyResult { } #[pyfunction] -fn truncate_lnglat(lng: f64, lat: f64) -> PyResult<(f64, f64)> { +fn truncate_lnglat(lng: f64, lat: f64) -> (f64, f64) { let ll = utiles::LngLat::new(lng, lat); let truncated = utiles::truncate_lnglat(&ll); - Ok((truncated.lng(), truncated.lat())) + (truncated.lng(), truncated.lat()) } #[pyclass] @@ -409,8 +373,8 @@ impl TilesGenerator { slf.iter.next() } - fn __len__(slf: PyRefMut<'_, Self>) -> PyResult { - Ok(slf.length as usize) + fn __len__(slf: PyRefMut<'_, Self>) -> usize { + slf.length as usize } } @@ -474,11 +438,6 @@ fn tiles_list( .collect::>() } -#[pyfunction] -fn xyz(x: u32, y: u32, z: u8) -> PyTile { - PyTile::new(x, y, z) -} - #[derive(FromPyObject, Debug)] enum CoordsExtractor<'a> { ListVecF64(Vec>), @@ -601,9 +560,7 @@ fn merge(merge_set: &HashSet) -> (HashSet, bool) { let mut upwards_merge: HashMap> = HashMap::new(); for tile in merge_set { let tile_parent = tile.parent(None); - let children_set = upwards_merge - .entry(tile_parent) - .or_insert_with(HashSet::new); + let children_set = upwards_merge.entry(tile_parent).or_default(); children_set.insert(*tile); } let mut current_tileset: Vec = Vec::new(); @@ -680,6 +637,11 @@ fn coords(py: Python, obj: &PyAny) -> PyResult> { // } // } +#[pyfunction] +fn geotransform2optzoom(geotransform: (f64, f64, f64, f64, f64, f64)) -> u8 { + utiles::geotransform2optzoom(geotransform) +} + #[pyfunction] fn geojson_bounds(py: Python, obj: &PyAny) -> PyResult { let coordsvec = _coords(py, obj); @@ -691,7 +653,7 @@ fn geojson_bounds(py: Python, obj: &PyAny) -> PyResult { for (lng, lat) in coordsvec { if lat <= -90.0 || lat >= 90.0 { - return Err(PyErr::new::(format!( + Err(PyErr::new::(format!( "Invalid latitude: {lat}" )))?; } @@ -742,11 +704,11 @@ fn libutiles(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(parse_tile_arg, m)?)?; m.add_function(wrap_pyfunction!(_parse_tile_arg, m)?)?; m.add_function(wrap_pyfunction!(minmax, m)?)?; - m.add_function(wrap_pyfunction!(ul, m)?)?; - m.add_function(wrap_pyfunction!(bounds, m)?)?; - m.add_function(wrap_pyfunction!(xy, m)?)?; - m.add_function(wrap_pyfunction!(_xy, m)?)?; - m.add_function(wrap_pyfunction!(lnglat, m)?)?; + m.add_function(wrap_pyfunction!(pyfns::ul, m)?)?; + m.add_function(wrap_pyfunction!(pyfns::bounds, m)?)?; + m.add_function(wrap_pyfunction!(pyfns::xy, m)?)?; + m.add_function(wrap_pyfunction!(pyfns::_xy, m)?)?; + m.add_function(wrap_pyfunction!(pyfns::lnglat, m)?)?; m.add_function(wrap_pyfunction!(xy_bounds, m)?)?; m.add_function(wrap_pyfunction!(tile, m)?)?; m.add_function(wrap_pyfunction!(parent, m)?)?; @@ -767,7 +729,7 @@ fn libutiles(_py: Python<'_>, m: &PyModule) -> PyResult<()> { // utiles functions m.add_function(wrap_pyfunction!(tiles_count, m)?)?; m.add_function(wrap_pyfunction!(tiles_list, m)?)?; - m.add_function(wrap_pyfunction!(xyz, m)?)?; + m.add_function(wrap_pyfunction!(pyfns::xyz, m)?)?; m.add_function(wrap_pyfunction!(parse_tiles, m)?)?; m.add_function(wrap_pyfunction!(xyz2quadkey, m)?)?; m.add_function(wrap_pyfunction!(quadkey2xyz, m)?)?; @@ -776,6 +738,7 @@ fn libutiles(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(pmtileid2xyz, m)?)?; m.add_function(wrap_pyfunction!(qk2xyz, m)?)?; m.add_function(wrap_pyfunction!(from_pmtileid, m)?)?; + m.add_function(wrap_pyfunction!(geotransform2optzoom, m)?)?; // tiletype m.add_function(wrap_pyfunction!(tiletype, m)?)?; diff --git a/src/pyfns.rs b/src/pyfns.rs new file mode 100644 index 00000000..4a23f1fc --- /dev/null +++ b/src/pyfns.rs @@ -0,0 +1,56 @@ +use crate::pyutiles::pylnglat::PyLngLat; +use crate::pyutiles::pylnglatbbox::PyLngLatBbox; +use crate::pyutiles::pytile::PyTile; +use pyo3::exceptions::PyValueError; +use pyo3::types::PyTuple; +use pyo3::{pyfunction, PyErr, PyResult}; + +#[pyfunction] +pub fn xyz(x: u32, y: u32, z: u8) -> PyTile { + PyTile::new(x, y, z) +} + +#[pyfunction] +#[pyo3(signature = (* args))] +pub fn ul(args: &PyTuple) -> PyResult { + let tile = crate::parse_tile_arg(args)?; + let lnglat = tile.ul(); + Ok(lnglat) +} + +#[pyfunction] +pub fn xy(lng: f64, lat: f64, truncate: Option) -> (f64, f64) { + utiles::xy(lng, lat, truncate) +} + +#[pyfunction] +pub fn _xy(lng: f64, lat: f64, truncate: Option) -> PyResult<(f64, f64)> { + let trunc = truncate.unwrap_or(false); + if !trunc && (lat <= -90.0 || lat >= 90.0) { + Err(PyErr::new::(format!( + "Invalid latitude: {lat}" + )))?; + } + let xy = utiles::_xy(lng, lat, truncate); + match xy { + Ok(xy) => Ok(xy), + Err(_e) => Err(PyErr::new::(format!( + "Invalid latitude: {lat}" + )))?, + } +} + +#[pyfunction] +pub fn lnglat(x: f64, y: f64, truncate: Option) -> PyLngLat { + // let trunc = truncate.unwrap_or(false); + let lnglat = utiles::lnglat(x, y, truncate); + PyLngLat::new(lnglat.lng(), lnglat.lat()) +} + +#[pyfunction] +#[pyo3(signature = (* args))] +pub fn bounds(args: &PyTuple) -> PyResult { + let tile = crate::parse_tile_arg(args)?; + let bbox = tile.bounds(); + Ok(bbox) +} diff --git a/src/pyutiles/pybbox.rs b/src/pyutiles/pybbox.rs index dccc35b8..042816bd 100644 --- a/src/pyutiles/pybbox.rs +++ b/src/pyutiles/pybbox.rs @@ -29,10 +29,10 @@ impl PyBbox { } #[classmethod] - pub fn from_tile(_cls: &PyType, tile: &PyTile) -> PyResult { + pub fn from_tile(_cls: &PyType, tile: &PyTile) -> Self { let ul = utiles::ul(tile.xyz.x, tile.xyz.y, tile.xyz.z); let lr = utiles::lr(tile.xyz.x, tile.xyz.y, tile.xyz.z); - Ok(Self::new(ul.lng(), lr.lat(), lr.lng(), ul.lat())) + Self::new(ul.lng(), lr.lat(), lr.lng(), ul.lat()) } pub fn __str__(&self) -> String { @@ -50,23 +50,23 @@ impl PyBbox { } #[getter] - pub fn left(&self) -> PyResult { - Ok(self.bbox.left()) + pub fn left(&self) -> f64 { + self.bbox.left() } #[getter] - pub fn bottom(&self) -> PyResult { - Ok(self.bbox.bottom()) + pub fn bottom(&self) -> f64 { + self.bbox.bottom() } #[getter] - pub fn right(&self) -> PyResult { - Ok(self.bbox.right()) + pub fn right(&self) -> f64 { + self.bbox.right() } #[getter] - pub fn top(&self) -> PyResult { - Ok(self.bbox.top()) + pub fn top(&self) -> f64 { + self.bbox.top() } #[getter] diff --git a/src/pyutiles/pylnglat.rs b/src/pyutiles/pylnglat.rs index 2461a6a0..485dce2f 100644 --- a/src/pyutiles/pylnglat.rs +++ b/src/pyutiles/pylnglat.rs @@ -20,9 +20,9 @@ impl PyLngLat { } #[classmethod] - pub fn from_tile(_cls: &PyType, tile: &PyTile) -> PyResult { + pub fn from_tile(_cls: &PyType, tile: &PyTile) -> Self { let ll = utiles::ul(tile.xyz.x, tile.xyz.y, tile.xyz.z); - Ok(Self::new(ll.lng(), ll.lat())) + Self::new(ll.lng(), ll.lat()) } pub fn __repr__(&self) -> String { @@ -38,13 +38,13 @@ impl PyLngLat { } #[getter] - pub fn lng(&self) -> PyResult { - Ok(self._lng()) + pub fn lng(&self) -> f64 { + self._lng() } #[getter] - pub fn lat(&self) -> PyResult { - Ok(self._lat()) + pub fn lat(&self) -> f64 { + self._lat() } pub fn __str__(&self) -> String { diff --git a/src/pyutiles/pylnglatbbox.rs b/src/pyutiles/pylnglatbbox.rs index d1a72dad..80f3d155 100644 --- a/src/pyutiles/pylnglatbbox.rs +++ b/src/pyutiles/pylnglatbbox.rs @@ -59,30 +59,30 @@ impl PyLngLatBbox { } #[classmethod] - pub fn from_tile(_cls: &PyType, tile: &PyTile) -> PyResult { + pub fn from_tile(_cls: &PyType, tile: &PyTile) -> Self { let ul = utiles::ul(tile.xyz.x, tile.xyz.y, tile.xyz.z); let lr = utiles::lr(tile.xyz.x, tile.xyz.y, tile.xyz.z); - Ok(Self::new(ul.lng(), lr.lat(), lr.lng(), ul.lat())) + Self::new(ul.lng(), lr.lat(), lr.lng(), ul.lat()) } #[getter] - pub fn west(&self) -> PyResult { - Ok(self.bbox.west()) + pub fn west(&self) -> f64 { + self.bbox.west() } #[getter] - pub fn south(&self) -> PyResult { - Ok(self.bbox.south()) + pub fn south(&self) -> f64 { + self.bbox.south() } #[getter] - pub fn east(&self) -> PyResult { - Ok(self.bbox.east()) + pub fn east(&self) -> f64 { + self.bbox.east() } #[getter] - pub fn north(&self) -> PyResult { - Ok(self.bbox.north()) + pub fn north(&self) -> f64 { + self.bbox.north() } pub fn members(&self) -> (f64, f64, f64, f64) { diff --git a/src/pyutiles/pytile.rs b/src/pyutiles/pytile.rs index 444bc1eb..9a0d2667 100644 --- a/src/pyutiles/pytile.rs +++ b/src/pyutiles/pytile.rs @@ -23,6 +23,7 @@ use crate::pyutiles::pylnglat::PyLngLat; use crate::pyutiles::pylnglatbbox::PyLngLatBbox; use std::hash::{Hash, Hasher}; use utiles::bbox::BBox; +use utiles::TileLike; /// `PyTile` macro to create a new tile. /// - do you need this? probably not @@ -134,9 +135,9 @@ impl PyTile { } #[classmethod] - pub fn from_pmtileid(_cls: &PyType, tileid: u64) -> PyResult { + pub fn from_pmtileid(_cls: &PyType, tileid: u64) -> Self { let xyz = Tile::from_pmtileid(tileid); - Ok(PyTile::from(xyz)) + PyTile::from(xyz) } pub fn pmtileid(&self) -> u64 { @@ -154,9 +155,9 @@ impl PyTile { lat: f64, zoom: u8, truncate: Option, - ) -> PyResult { + ) -> Self { let xyz = Tile::from_lnglat_zoom(lng, lat, zoom, truncate); - Ok(PyTile::from(xyz)) + PyTile::from(xyz) } pub fn __repr__(&self) -> String { @@ -164,18 +165,18 @@ impl PyTile { } #[getter] - pub fn x(&self) -> PyResult { - Ok(self.xyz.x) + pub fn x(&self) -> u32 { + self.xyz.x } #[getter] - pub fn y(&self) -> PyResult { - Ok(self.xyz.y) + pub fn y(&self) -> u32 { + self.xyz.y } #[getter] - pub fn z(&self) -> PyResult { - Ok(self.xyz.z) + pub fn z(&self) -> u8 { + self.xyz.z } pub fn __str__(&self) -> String { @@ -305,6 +306,7 @@ impl PyTile { pub fn ul(&self) -> PyLngLat { self.xyz.ul().into() } + pub fn ll(&self) -> PyLngLat { self.xyz.ll().into() } diff --git a/tests/cli/test_mt.py b/tests/cli/test_mt.py index 1cd793c6..9b76f6d3 100644 --- a/tests/cli/test_mt.py +++ b/tests/cli/test_mt.py @@ -6,8 +6,10 @@ import pytest +from utiles.dev.testing import run_cli as _run_cli -def _run_cli( + +def _run_cli_old( args: list[str] | None, input: str | None = None, ) -> CompletedProcess[str]: @@ -96,7 +98,7 @@ def test_cli_tiles_arg(self) -> None: assert result.returncode == 0 assert result.stdout == "[3413, 6202, 14]\n[3413, 6203, 14]\n" - def test_cli_tiles_geosjon(self) -> None: + def test_cli_tiles_geojson(self) -> None: collection = stringify( { "features": [ @@ -199,7 +201,7 @@ def test_cli_tiles_bounding_tiles_seq(self) -> None: assert result.returncode == 0 assert result.stdout == "\x1e\n[0, 0, 0]\n" - def test_cli_bounding_tile_geosjon(self) -> None: + def test_cli_bounding_tile_geojson(self) -> None: collection_dict = { "features": [ { diff --git a/tests/test_tiletype.py b/tests/test_tiletype.py index 52bd972c..806a9efe 100644 --- a/tests/test_tiletype.py +++ b/tests/test_tiletype.py @@ -2,6 +2,7 @@ from typing import Union import pytest +from pytest_benchmark.fixture import BenchmarkFixture import utiles @@ -135,25 +136,25 @@ def test_tiletype_rs( assert ttype == expected -# @pytest.mark.parametrize( -# "tile", -# TEST_TILES_BYTES, -# ) -# def test_benchmark_tiletype_py( -# tile: tuple[str, bytes], -# benchmark, -# ): -# filename, buffer = tile -# benchmark(tiletype, buffer) -# -# -# @pytest.mark.parametrize( -# "tile", -# TEST_TILES_BYTES, -# ) -# def test_benchmark_tiletype_rs( -# tile: tuple[str, bytes], -# benchmark, -# ): -# filename, buffer = tile -# benchmark(utiles.tiletype_str, buffer) +@pytest.mark.parametrize( + "tile", + TEST_TILES_BYTES, +) +def test_benchmark_tiletype_py( + tile: tuple[str, bytes], + benchmark: BenchmarkFixture, +) -> None: + filename, buffer = tile + benchmark(tiletype, buffer) + + +@pytest.mark.parametrize( + "tile", + TEST_TILES_BYTES, +) +def test_benchmark_tiletype_rs( + tile: tuple[str, bytes], + benchmark: BenchmarkFixture, +) -> None: + filename, buffer = tile + benchmark(utiles.tiletype_str, buffer)