From 024a8b130dc4da16a8eea89fea2eac214155c338 Mon Sep 17 00:00:00 2001 From: Frank Jimenez Date: Thu, 13 Feb 2025 21:48:08 +0000 Subject: [PATCH 1/7] feat: property error --- rust/mlt/src/error.rs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 rust/mlt/src/error.rs diff --git a/rust/mlt/src/error.rs b/rust/mlt/src/error.rs new file mode 100644 index 00000000..7878d0e3 --- /dev/null +++ b/rust/mlt/src/error.rs @@ -0,0 +1,9 @@ +use thiserror::Error; + +pub type MltResult = Result; + +#[derive(Error, Debug)] +pub enum MltError { + #[error("Unable to parse property: {0}")] + PropertyParseError(String), +} From b60bfc9b650d5c7dddf30257b99d8cfa0d1499fd Mon Sep 17 00:00:00 2001 From: Frank Jimenez Date: Thu, 13 Feb 2025 21:49:31 +0000 Subject: [PATCH 2/7] chore: update cargo & ci --- rust/mlt/.github/workflows/ci.yml | 52 +++ rust/mlt/Cargo.lock | 690 ++++++++++++++++++++++++++++++ rust/mlt/Cargo.toml | 17 + rust/mlt/justfile | 110 +++++ 4 files changed, 869 insertions(+) create mode 100644 rust/mlt/.github/workflows/ci.yml create mode 100644 rust/mlt/Cargo.lock create mode 100644 rust/mlt/Cargo.toml create mode 100644 rust/mlt/justfile diff --git a/rust/mlt/.github/workflows/ci.yml b/rust/mlt/.github/workflows/ci.yml new file mode 100644 index 00000000..5c202679 --- /dev/null +++ b/rust/mlt/.github/workflows/ci.yml @@ -0,0 +1,52 @@ +name: Build + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + release: + types: [ published ] + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: taiki-e/install-action@v2 + with: { tool: just } + - uses: actions/checkout@v4 +# +# Uncomment this and below once the crate has been published to crates.io +# +# - name: Ensure this crate has not yet been published (on release) +# if: github.event_name == 'release' && matrix.type == 'latest' +# run: just check-if-published + - uses: Swatinem/rust-cache@v2 + if: github.event_name != 'release' && github.event_name != 'workflow_dispatch' + - run: just -v ci-test +# - name: Check semver +# uses: obi1kenobi/cargo-semver-checks-action@v2 +# - name: Test packaging for publish +# run: | +# rustup install nightly --profile minimal +# just test-publish + + msrv: + name: Test MSRV + runs-on: ubuntu-latest + steps: + - uses: taiki-e/install-action@v2 + with: { tool: just } + - uses: actions/checkout@v4 + - uses: Swatinem/rust-cache@v2 + if: github.event_name != 'release' && github.event_name != 'workflow_dispatch' + - name: Read crate metadata + id: metadata + run: echo "rust-version=$(sed -ne 's/rust-version *= *\"\(.*\)\"/\1/p' Cargo.toml)" >> $GITHUB_OUTPUT + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ steps.metadata.outputs.rust-version }} + components: rustfmt + - run: just -v ci-test-msrv diff --git a/rust/mlt/Cargo.lock b/rust/mlt/Cargo.lock new file mode 100644 index 00000000..a7b07764 --- /dev/null +++ b/rust/mlt/Cargo.lock @@ -0,0 +1,690 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[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.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[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.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[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.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "geo-types" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bd1157f0f936bf0cd68dec91e8f7c311afe60295574d62b70d4861a1bfdf2d9" +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 = [ + "log", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "geozero" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5f28f34864745eb2f123c990c6ffd92c1584bd39439b3f27ff2a0f4ea5b309b" +dependencies = [ + "dup-indexer", + "geo-types", + "geojson", + "log", + "prost 0.11.9", + "prost-build 0.11.9", + "serde_json", + "thiserror 1.0.69", + "wkt", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi", + "windows-targets", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "log" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mlt" +version = "0.1.0" +dependencies = [ + "geozero", + "indexmap", + "prost 0.13.5", + "prost-build 0.13.5", + "prost-types 0.13.5", + "thiserror 2.0.11", +] + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "once_cell" +version = "1.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[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 = "prettyplease" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" +dependencies = [ + "proc-macro2", + "syn 2.0.98", +] + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +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 0.11.9", +] + +[[package]] +name = "prost" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes", + "prost-derive 0.13.5", +] + +[[package]] +name = "prost-build" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +dependencies = [ + "bytes", + "heck", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph", + "prettyplease 0.1.25", + "prost 0.11.9", + "prost-types 0.11.9", + "regex", + "syn 1.0.109", + "tempfile", + "which", +] + +[[package]] +name = "prost-build" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" +dependencies = [ + "heck", + "itertools", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease 0.2.29", + "prost 0.13.5", + "prost-types 0.13.5", + "regex", + "syn 2.0.98", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost 0.11.9", +] + +[[package]] +name = "prost-types" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" +dependencies = [ + "prost 0.13.5", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "ryu" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "serde_json" +version = "1.0.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[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.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" +dependencies = [ + "cfg-if", + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl 2.0.11", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "unicode-ident" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" + +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + +[[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 = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] + +[[package]] +name = "wkt" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54f7f1ff4ea4c18936d6cd26a6fd24f0003af37e951a8e0e8b9e9a2d0bd0a46d" +dependencies = [ + "geo-types", + "log", + "num-traits", + "thiserror 1.0.69", +] diff --git a/rust/mlt/Cargo.toml b/rust/mlt/Cargo.toml new file mode 100644 index 00000000..a5b422a3 --- /dev/null +++ b/rust/mlt/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "mlt" +version = "0.1.0" +edition = "2021" + +[dependencies] +thiserror = "2.0.11" +geozero = { version = "0.14", features = ["with-mvt"] } +prost = "0.13.5" +prost-types = "0.13.5" +indexmap = "2.7.1" + +[build-dependencies] +prost-build = "0.13.5" + +[lints.rust] +dead_code = "allow" diff --git a/rust/mlt/justfile b/rust/mlt/justfile new file mode 100644 index 00000000..77d63b4b --- /dev/null +++ b/rust/mlt/justfile @@ -0,0 +1,110 @@ +#!/usr/bin/env just --justfile + +@_default: + just --list + +# Clean all build artifacts +clean: + cargo clean + rm -f Cargo.lock + +# Update dependencies, including breaking changes +update: + cargo +nightly -Z unstable-options update --breaking + cargo update + +# Run cargo clippy +clippy: + cargo clippy --all-targets --workspace -- -D warnings + +# Test code formatting +test-fmt: + cargo fmt --all -- --check + +# Run cargo fmt +fmt: + cargo +nightly fmt -- --config imports_granularity=Module,group_imports=StdExternalCrate + +# Build and open code documentation +docs: + cargo doc --no-deps --open + +# Quick compile +check: + cargo check --all-targets --workspace + +# Default build +build: + cargo build --all-targets --workspace + +# Run all tests +test *ARGS: build + cargo test --all-targets --workspace {{ARGS}} + +# Find the minimum supported Rust version. Install it with `cargo install cargo-msrv` +msrv: + cargo msrv find --component rustfmt -- {{just_executable()}} ci-test-msrv + +# Find unused dependencies. Install it with `cargo install cargo-udeps` +udeps: + cargo +nightly udeps --all-targets --workspace + +# Check semver compatibility with prior published version. Install it with `cargo install cargo-semver-checks` +semver *ARGS: + cargo semver-checks {{ARGS}} + +# Generate and show coverage report. Requires grcov to be installed. +grcov: + #!/usr/bin/env bash + set -euo pipefail + find . -name '*.profraw' | xargs rm + rm -rf ./target/debug/coverage + export LLVM_PROFILE_FILE="mlt-%p-%m.profraw" + export RUSTFLAGS="-Cinstrument-coverage" + cargo build --all-targets --workspace + cargo test --all-targets --workspace + grcov . -s . --binary-path ./target/debug/ -t html --branch --ignore-not-existing -o ./target/debug/coverage/ + open ./target/debug/coverage/index.html + +# Use the experimental workspace publishing with --dry-run. Requires nightly Rust. +test-publish: + cargo +nightly -Z package-workspace publish --dry-run + +# Run tests, and accept their results. Requires insta to be installed. +bless: + TRYBUILD=overwrite cargo insta test --accept + +# Test documentation +test-doc: + cargo test --doc + cargo doc --no-deps + +rust-info: + rustc --version + cargo --version + +# Run tests only relevant to the latest version +ci-test-extras: test-doc + +# Run all tests as expected by CI +ci-test: rust-info test-fmt clippy test build + +# Run minimal subset of tests to ensure compatibility with MSRV +ci-test-msrv: rust-info test + +# Verify that the current version of the crate is not the same as the one published on crates.io +check-if-published: + #!/usr/bin/env bash + set -euo pipefail + LOCAL_VERSION="$(grep '^version =' Cargo.toml | sed -E 's/version = "([^"]*)".*/\1/')" + echo "Detected crate version: $LOCAL_VERSION" + CRATE_NAME="$(grep '^name =' Cargo.toml | head -1 | sed -E 's/name = "(.*)"/\1/')" + echo "Detected crate name: $CRATE_NAME" + PUBLISHED_VERSION="$(cargo search ${CRATE_NAME} | grep "^${CRATE_NAME} =" | sed -E 's/.* = "(.*)".*/\1/')" + echo "Published crate version: $PUBLISHED_VERSION" + if [ "$LOCAL_VERSION" = "$PUBLISHED_VERSION" ]; then + echo "ERROR: The current crate version has already been published." + exit 1 + else + echo "The current crate version has not yet been published." + fi From 766c12441b86dd5cdd5a250246b81ff56fefb0a9 Mon Sep 17 00:00:00 2001 From: Frank Jimenez Date: Thu, 13 Feb 2025 21:50:10 +0000 Subject: [PATCH 3/7] feat: prost mlt_tileset_metadata.proto --- rust/mlt/build.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 rust/mlt/build.rs diff --git a/rust/mlt/build.rs b/rust/mlt/build.rs new file mode 100644 index 00000000..5f5a8f1a --- /dev/null +++ b/rust/mlt/build.rs @@ -0,0 +1,30 @@ +use std::env; +use std::fs; +use std::path::PathBuf; + +fn main() { + let out_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("src/metadata"); + + // Ensure the output directory exists + fs::create_dir_all(&out_dir).unwrap(); + + // Generate the file using prost_build + prost_build::Config::new() + .out_dir(&out_dir) + .compile_protos( + &["../../spec/schema/mlt_tileset_metadata.proto"], + &["../../spec/schema/"], + ) + .unwrap(); + + // Define the original and new file paths + let original_file = out_dir.join("mlt.rs"); + let new_file = out_dir.join("proto_tileset.rs"); + + // Rename the file + if original_file.exists() { + fs::rename(&original_file, &new_file).unwrap(); + } else { + panic!("Generated file 'mlt.rs' not found!"); + } +} From 5281852e0f8296a530007592da9cb1aa22064e53 Mon Sep 17 00:00:00 2001 From: Frank Jimenez Date: Thu, 13 Feb 2025 21:50:36 +0000 Subject: [PATCH 4/7] chore: notes on parquet and prost --- rust/mlt/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 rust/mlt/README.md diff --git a/rust/mlt/README.md b/rust/mlt/README.md new file mode 100644 index 00000000..05a09c43 --- /dev/null +++ b/rust/mlt/README.md @@ -0,0 +1,5 @@ +# Maplibre Tiles RS + +Notes: +* [This](https://baarse.substack.com/p/fast-parquet-reading-from-java-to) may be useful as parquet has similar format +* [proto_tileset.rs](src/metadata/proto_tileset.rs) is a generated via prost - see [build.rs](build.rs) From fe80e39f91a0cf71b9f612301f7dd774b21c60fc Mon Sep 17 00:00:00 2001 From: Frank Jimenez Date: Sun, 16 Feb 2025 21:53:44 +0000 Subject: [PATCH 5/7] feat: mlt metadata poc --- rust/mlt/src/converter/mlt.rs | 278 +++++++++++++++++++++ rust/mlt/src/converter/mod.rs | 2 + rust/mlt/src/converter/mvt.rs | 25 ++ rust/mlt/src/data/mod.rs | 10 + rust/mlt/src/error.rs | 2 + rust/mlt/src/lib.rs | 6 + rust/mlt/src/metadata/mod.rs | 1 + rust/mlt/src/metadata/proto_tileset.rs | 327 +++++++++++++++++++++++++ rust/mlt/tests/mlt_decoder_test.rs | 0 9 files changed, 651 insertions(+) create mode 100644 rust/mlt/src/converter/mlt.rs create mode 100644 rust/mlt/src/converter/mod.rs create mode 100644 rust/mlt/src/converter/mvt.rs create mode 100644 rust/mlt/src/data/mod.rs create mode 100644 rust/mlt/src/lib.rs create mode 100644 rust/mlt/src/metadata/mod.rs create mode 100644 rust/mlt/src/metadata/proto_tileset.rs create mode 100644 rust/mlt/tests/mlt_decoder_test.rs diff --git a/rust/mlt/src/converter/mlt.rs b/rust/mlt/src/converter/mlt.rs new file mode 100644 index 00000000..3e2712af --- /dev/null +++ b/rust/mlt/src/converter/mlt.rs @@ -0,0 +1,278 @@ +use std::u64; + +use crate::converter::mvt::MapboxVectorTile; +use crate::error::MltError; +use crate::metadata::proto_tileset::{ + column, complex_column::Type::PhysicalType, field, scalar_column, Column, ColumnScope, + ComplexColumn, ComplexType, FeatureTableSchema, Field, ScalarColumn, ScalarType, + TileSetMetadata, +}; +use crate::metadata::proto_tileset::{scalar_field, ScalarField}; +use crate::MltResult; +use geozero::mvt; +use indexmap::IndexMap; + +use super::mvt::ColumnMapping; + +const VERSION: i32 = 1; +const ID_COLUMN_NAME: &str = "id"; +const GEOMETRY_COLUMN_NAME: &str = "geometry"; + +fn create_tileset_metadata( + mvt: MapboxVectorTile, + is_id_present: bool, + column_mappings: Option>, +) -> MltResult { + let mut tileset = TileSetMetadata { + version: VERSION, + name: None, + description: None, + feature_tables: Vec::new(), + attribution: None, + min_zoom: None, + max_zoom: None, + bounds: Vec::new(), + center: Vec::new(), + }; + + for layer in &mvt.layers { + let mut feature_table_scheme: IndexMap = IndexMap::new(); + + if is_id_present { + let id_metadata = Column { + name: ID_COLUMN_NAME.to_string(), + nullable: false, + column_scope: ColumnScope::Feature.into(), + r#type: { + if layer.features.iter().all(|f| match f.id { + Some(id) => id <= i32::MAX as u64, + None => false, + }) { + Some(column::Type::ScalarType(ScalarColumn { + r#type: Some(scalar_column::Type::PhysicalType( + ScalarType::Uint32 as i32, + )), + })) + } else { + Some(column::Type::ScalarType(ScalarColumn { + r#type: Some(scalar_column::Type::PhysicalType( + ScalarType::Uint64 as i32, + )), + })) + } + }, + }; + feature_table_scheme.insert(ID_COLUMN_NAME.to_string(), id_metadata); + } + + let geometry_data = Column { + name: GEOMETRY_COLUMN_NAME.to_string(), + nullable: false, + column_scope: ColumnScope::Feature.into(), + r#type: Some(column::Type::ComplexType(ComplexColumn { + children: Vec::new(), + r#type: Some(PhysicalType(ComplexType::Geometry as i32)), + })), + }; + feature_table_scheme.insert(GEOMETRY_COLUMN_NAME.to_string(), geometry_data); + + let mut properties: Vec<(String, mvt::tile::Value)> = layer + .keys + .iter() + .zip(layer.values.iter()) + .map(|(k, v)| (k.replace("_", ":"), v.clone())) + .collect(); + properties.sort_by(|(k1, _), (k2, _)| k1.cmp(k2)); + + let mut complex_property_column_schemes: IndexMap = IndexMap::new(); + + for (property_key, property_value) in properties.iter() { + if feature_table_scheme.contains_key(property_key) { + continue; + } + let scalar_type = get_scalar_type(&property_value)?; + + // Column Mappings: the Java code does not have a unit test for this block of code. + // Hard to determine the expected behavior. + if column_mappings.is_some() { + if column_mappings.as_ref().map_or(false, |mappings| { + mappings + .iter() + .any(|m| property_key == m.mvt_property_prefix.as_str()) + }) && !complex_property_column_schemes.contains_key(property_key) + { + // case where the top-level field is present like name (name:de, name:us, ...) and has a value. + // In this case the field is mapped to the name default. + let child_field = Field { + name: Some("default".to_string()), + nullable: Some(true), + r#type: Some(field::Type::ScalarField(ScalarField { + r#type: Some(scalar_field::Type::PhysicalType(scalar_type as i32)), + })), + }; + let field_metadata_builder = ComplexColumn { + children: vec![child_field], + r#type: Some(PhysicalType(ComplexType::Struct as i32)), + }; + complex_property_column_schemes + .insert(property_key.clone(), field_metadata_builder); + continue; + } else if column_mappings.as_ref().map_or(false, |mappings| { + mappings + .iter() + .any(|m| property_key == m.mvt_property_prefix.as_str()) + }) && complex_property_column_schemes.contains_key(property_key) + && complex_property_column_schemes + .get(property_key) + .map_or(false, |column| { + column + .children + .iter() + .any(|c| c.name.as_deref() == Some("default")) + }) + { + // Case where the top-level field such as name is not present in the first feature + let child_field = Field { + name: Some("default".to_string()), + nullable: Some(true), + r#type: Some(field::Type::ScalarField(ScalarField { + r#type: Some(scalar_field::Type::PhysicalType(scalar_type as i32)), + })), + }; + let column_mapping = column_mappings + .as_ref() + .expect("columnMappings.get() must not be null") + .iter() + .find(|m| property_key == m.mvt_property_prefix.as_str()) + .expect("No matching column mapping found"); + complex_property_column_schemes + .get_mut(column_mapping.mvt_property_prefix.as_str()) + .expect("No matching column mapping found") + .children + .push(child_field); + continue; + } else if column_mappings.as_ref().map_or(false, |mappings| { + mappings.iter().any(|m| { + property_key.contains(&m.mvt_property_prefix) + && property_key.contains(&m.mvt_delimiter_sign) + }) + }) { + let column_mapping = column_mappings + .as_ref() + .expect("columnMappings.get() must not be null") + .iter() + .find(|m| property_key == m.mvt_property_prefix.as_str()) + .expect("No matching column mapping found"); + let field_name = property_key + .split(&column_mapping.mvt_delimiter_sign) + .nth(1) + .expect("No second element found in split"); + let children = Field { + name: Some(field_name.to_string()), + nullable: Some(true), + r#type: Some(field::Type::ScalarField(ScalarField { + r#type: Some(scalar_field::Type::PhysicalType(scalar_type as i32)), + })), + }; + if complex_property_column_schemes + .contains_key(column_mapping.mvt_property_prefix.as_str()) + { + // add the nested properties to the parent like the name:* properties to the name parent struct + if !complex_property_column_schemes + .get(column_mapping.mvt_property_prefix.as_str()) + .expect("No matching column mapping found") + .children + .iter() + .any(|c| c.name.as_deref() == Some(field_name)) + { + complex_property_column_schemes + .get_mut(column_mapping.mvt_property_prefix.as_str()) + .expect("No matching column mapping found") + .children + .push(children); + }; + } else { + // Case where there is no explicit property available which serves as the name + // for the top-level field. For example there is no name property only name:* + let complex_column_builder = ComplexColumn { + children: vec![children], + r#type: Some(PhysicalType(ComplexType::Struct as i32)), + }; + complex_property_column_schemes.insert( + column_mapping.mvt_property_prefix.clone(), + complex_column_builder, + ); + } + continue; + } + } + + let column_scheme = Column { + name: property_key.clone(), + nullable: true, + column_scope: ColumnScope::Feature.into(), + r#type: Some(column::Type::ScalarType(ScalarColumn { + r#type: Some(scalar_column::Type::PhysicalType(scalar_type as i32)), + })), + }; + feature_table_scheme.insert(property_key.clone(), column_scheme); + } + + let feature_table_schema_builder = FeatureTableSchema { + name: layer.name.clone(), + columns: feature_table_scheme.into_iter().map(|(_, v)| v).collect(), + }; + + tileset.feature_tables.push(feature_table_schema_builder); + } + + Ok(tileset) +} + +fn get_scalar_type(value: &mvt::tile::Value) -> MltResult { + match value { + mvt::tile::Value { + string_value: Some(_), + .. + } => Ok(ScalarType::String), + mvt::tile::Value { + float_value: Some(_), + .. + } => Ok(ScalarType::Float), + mvt::tile::Value { + double_value: Some(_), + .. + } => Ok(ScalarType::Double), + mvt::tile::Value { + int_value: Some(_), .. + } => Ok(ScalarType::Int32), + mvt::tile::Value { + uint_value: Some(_), + .. + } => Ok(ScalarType::Uint32), + mvt::tile::Value { + bool_value: Some(_), + .. + } => Ok(ScalarType::Boolean), + _ => Err(MltError::UnsupportedKeyType( + "Unsupported key value type".to_string(), + )), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::converter::mvt::decode_mvt; + + #[test] + fn test_create_tileset_metadata() { + let data = &include_bytes!("../../../../test/fixtures/bing/4-12-6.mvt")[..]; + let tile = decode_mvt(data); + let metadata = create_tileset_metadata(tile.clone(), true, None); + assert_eq!( + metadata.unwrap().feature_tables.len(), + tile.layers.iter().count() + ); + } +} diff --git a/rust/mlt/src/converter/mod.rs b/rust/mlt/src/converter/mod.rs new file mode 100644 index 00000000..54e50908 --- /dev/null +++ b/rust/mlt/src/converter/mod.rs @@ -0,0 +1,2 @@ +mod mvt; +mod mlt; diff --git a/rust/mlt/src/converter/mvt.rs b/rust/mlt/src/converter/mvt.rs new file mode 100644 index 00000000..cd5727d5 --- /dev/null +++ b/rust/mlt/src/converter/mvt.rs @@ -0,0 +1,25 @@ +use geozero::mvt::{tile::Layer, Message, Tile}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ColumnMapping { + pub mvt_property_prefix: String, + pub mvt_delimiter_sign: String, + pub use_shared_dictionary_encoding: bool, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct MapboxVectorTile { + pub layers: Vec, +} + +pub fn decode_mvt(mvt_tile: &[u8]) -> MapboxVectorTile { + let mut tile = Tile::decode(mvt_tile).expect("Failed to decode MVT"); + for layer in &mut tile.layers { + if layer.extent() <= 0 { + layer.extent.get_or_insert(0); + } + } + MapboxVectorTile { + layers: tile.layers, + } +} diff --git a/rust/mlt/src/data/mod.rs b/rust/mlt/src/data/mod.rs new file mode 100644 index 00000000..444c3c6f --- /dev/null +++ b/rust/mlt/src/data/mod.rs @@ -0,0 +1,10 @@ +// public record Feature(long id, Geometry geometry, Map properties) {} + +// #[derive(Debug)] +// pub enum PropertyValue { +// String(String), +// Integer(i64), +// Float(f64), +// Boolean(bool), +// List(Vec), +// } diff --git a/rust/mlt/src/error.rs b/rust/mlt/src/error.rs index 7878d0e3..c78ea5ed 100644 --- a/rust/mlt/src/error.rs +++ b/rust/mlt/src/error.rs @@ -6,4 +6,6 @@ pub type MltResult = Result; pub enum MltError { #[error("Unable to parse property: {0}")] PropertyParseError(String), + #[error("Unsupported key value type: {0}")] + UnsupportedKeyType(String), } diff --git a/rust/mlt/src/lib.rs b/rust/mlt/src/lib.rs new file mode 100644 index 00000000..efd2b838 --- /dev/null +++ b/rust/mlt/src/lib.rs @@ -0,0 +1,6 @@ +mod error; +mod converter; +mod data; +mod metadata; + +pub use error::MltResult; diff --git a/rust/mlt/src/metadata/mod.rs b/rust/mlt/src/metadata/mod.rs new file mode 100644 index 00000000..91e3dab0 --- /dev/null +++ b/rust/mlt/src/metadata/mod.rs @@ -0,0 +1 @@ +pub mod proto_tileset; diff --git a/rust/mlt/src/metadata/proto_tileset.rs b/rust/mlt/src/metadata/proto_tileset.rs new file mode 100644 index 00000000..2acf8a60 --- /dev/null +++ b/rust/mlt/src/metadata/proto_tileset.rs @@ -0,0 +1,327 @@ +// This file is @generated by prost-build. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TileSetMetadata { + #[prost(int32, tag = "1")] + pub version: i32, + #[prost(message, repeated, tag = "2")] + pub feature_tables: ::prost::alloc::vec::Vec, + #[prost(string, optional, tag = "3")] + pub name: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "4")] + pub description: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "5")] + pub attribution: ::core::option::Option<::prost::alloc::string::String>, + #[prost(int32, optional, tag = "6")] + pub min_zoom: ::core::option::Option, + #[prost(int32, optional, tag = "7")] + pub max_zoom: ::core::option::Option, + /// order left, bottom, right, top in WGS84 + #[prost(double, repeated, tag = "8")] + pub bounds: ::prost::alloc::vec::Vec, + /// order longitude, latitude in WGS84 + #[prost(double, repeated, tag = "9")] + pub center: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct FeatureTableSchema { + #[prost(string, tag = "1")] + pub name: ::prost::alloc::string::String, + #[prost(message, repeated, tag = "2")] + pub columns: ::prost::alloc::vec::Vec, +} +/// Column are top-level types in the schema +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Column { + #[prost(string, tag = "1")] + pub name: ::prost::alloc::string::String, + /// specifies if the values are optional in the column and a present stream should be used + #[prost(bool, tag = "2")] + pub nullable: bool, + #[prost(enumeration = "ColumnScope", tag = "3")] + pub column_scope: i32, + #[prost(oneof = "column::Type", tags = "4, 5")] + pub r#type: ::core::option::Option, +} +/// Nested message and enum types in `Column`. +pub mod column { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Type { + #[prost(message, tag = "4")] + ScalarType(super::ScalarColumn), + #[prost(message, tag = "5")] + ComplexType(super::ComplexColumn), + } +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct ScalarColumn { + #[prost(oneof = "scalar_column::Type", tags = "4, 5")] + pub r#type: ::core::option::Option, +} +/// Nested message and enum types in `ScalarColumn`. +pub mod scalar_column { + #[derive(Clone, Copy, PartialEq, ::prost::Oneof)] + pub enum Type { + #[prost(enumeration = "super::ScalarType", tag = "4")] + PhysicalType(i32), + #[prost(enumeration = "super::LogicalScalarType", tag = "5")] + LogicalType(i32), + } +} +/// The type tree is flattened in to a list via a pre-order traversal +/// Represents a column if it is a root (top-level) type or a child of a nested type +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ComplexColumn { + /// The complex type Geometry and the logical type BINARY have no children since there layout is implicit known. + /// RangeMap has only one child specifying the type of the value since the key is always a vec2. + #[prost(message, repeated, tag = "6")] + pub children: ::prost::alloc::vec::Vec, + #[prost(oneof = "complex_column::Type", tags = "4, 5")] + pub r#type: ::core::option::Option, +} +/// Nested message and enum types in `ComplexColumn`. +pub mod complex_column { + #[derive(Clone, Copy, PartialEq, ::prost::Oneof)] + pub enum Type { + #[prost(enumeration = "super::ComplexType", tag = "4")] + PhysicalType(i32), + #[prost(enumeration = "super::LogicalComplexType", tag = "5")] + LogicalType(i32), + } +} +/// Fields define nested or leaf types in the schema as part of a complex type definition +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Field { + /// name and nullable are only needed in combination with a struct not for vec, list and map + /// Map -> has the order key type, value type + #[prost(string, optional, tag = "1")] + pub name: ::core::option::Option<::prost::alloc::string::String>, + #[prost(bool, optional, tag = "2")] + pub nullable: ::core::option::Option, + #[prost(oneof = "field::Type", tags = "3, 4")] + pub r#type: ::core::option::Option, +} +/// Nested message and enum types in `Field`. +pub mod field { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Type { + #[prost(message, tag = "3")] + ScalarField(super::ScalarField), + #[prost(message, tag = "4")] + ComplexField(super::ComplexField), + } +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct ScalarField { + #[prost(oneof = "scalar_field::Type", tags = "1, 2")] + pub r#type: ::core::option::Option, +} +/// Nested message and enum types in `ScalarField`. +pub mod scalar_field { + #[derive(Clone, Copy, PartialEq, ::prost::Oneof)] + pub enum Type { + #[prost(enumeration = "super::ScalarType", tag = "1")] + PhysicalType(i32), + #[prost(enumeration = "super::LogicalScalarType", tag = "2")] + LogicalType(i32), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ComplexField { + #[prost(message, repeated, tag = "3")] + pub children: ::prost::alloc::vec::Vec, + #[prost(oneof = "complex_field::Type", tags = "1, 2")] + pub r#type: ::core::option::Option, +} +/// Nested message and enum types in `ComplexField`. +pub mod complex_field { + #[derive(Clone, Copy, PartialEq, ::prost::Oneof)] + pub enum Type { + #[prost(enumeration = "super::ComplexType", tag = "1")] + PhysicalType(i32), + #[prost(enumeration = "super::LogicalComplexType", tag = "2")] + LogicalType(i32), + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ColumnScope { + /// 1:1 Mapping of property and feature -> id and geometry + Feature = 0, + /// For M-Values -> 1:1 Mapping for property and vertex + Vertex = 1, +} +impl ColumnScope { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Feature => "FEATURE", + Self::Vertex => "VERTEX", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "FEATURE" => Some(Self::Feature), + "VERTEX" => Some(Self::Vertex), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ScalarType { + Boolean = 0, + Int8 = 1, + Uint8 = 2, + Int32 = 3, + Uint32 = 4, + Int64 = 5, + Uint64 = 6, + Float = 7, + Double = 8, + String = 9, +} +impl ScalarType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Boolean => "BOOLEAN", + Self::Int8 => "INT_8", + Self::Uint8 => "UINT_8", + Self::Int32 => "INT_32", + Self::Uint32 => "UINT_32", + Self::Int64 => "INT_64", + Self::Uint64 => "UINT_64", + Self::Float => "FLOAT", + Self::Double => "DOUBLE", + Self::String => "STRING", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "BOOLEAN" => Some(Self::Boolean), + "INT_8" => Some(Self::Int8), + "UINT_8" => Some(Self::Uint8), + "INT_32" => Some(Self::Int32), + "UINT_32" => Some(Self::Uint32), + "INT_64" => Some(Self::Int64), + "UINT_64" => Some(Self::Uint64), + "FLOAT" => Some(Self::Float), + "DOUBLE" => Some(Self::Double), + "STRING" => Some(Self::String), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ComplexType { + /// fixed size binary with 2 values of the same type either signed or unsigned Int8, Int32, Int64 as well as Float or Double + Vec2 = 0, + /// fixed size binary with 2 values of the same type either signed or unsigned Int8, Int32, Int64 as well as Float or Double + Vec3 = 1, + /// vec2 for the VertexBuffer stream with additional information (streams) about the topology + Geometry = 2, + /// vec3 for the VertexBuffer stream with additional information (streams) about the topology + GeometryZ = 3, + List = 4, + Map = 5, + Struct = 6, +} +impl ComplexType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Vec2 => "VEC_2", + Self::Vec3 => "VEC_3", + Self::Geometry => "GEOMETRY", + Self::GeometryZ => "GEOMETRY_Z", + Self::List => "LIST", + Self::Map => "MAP", + Self::Struct => "STRUCT", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "VEC_2" => Some(Self::Vec2), + "VEC_3" => Some(Self::Vec3), + "GEOMETRY" => Some(Self::Geometry), + "GEOMETRY_Z" => Some(Self::GeometryZ), + "LIST" => Some(Self::List), + "MAP" => Some(Self::Map), + "STRUCT" => Some(Self::Struct), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum LogicalScalarType { + /// physical type: Int64 -> number of milliseconds since Unix epoch + Timestamp = 0, + /// physical type: Int32 -> number of days since Unix epoch + Date = 1, + /// physical type: String + Json = 2, +} +impl LogicalScalarType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Timestamp => "TIMESTAMP", + Self::Date => "DATE", + Self::Json => "JSON", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "TIMESTAMP" => Some(Self::Timestamp), + "DATE" => Some(Self::Date), + "JSON" => Some(Self::Json), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum LogicalComplexType { + /// physical type: list + Binary = 0, + /// physical type: map> -> special data structure which can be used for a efficient representation of linear referencing + RangeMap = 1, +} +impl LogicalComplexType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Binary => "BINARY", + Self::RangeMap => "RANGE_MAP", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "BINARY" => Some(Self::Binary), + "RANGE_MAP" => Some(Self::RangeMap), + _ => None, + } + } +} diff --git a/rust/mlt/tests/mlt_decoder_test.rs b/rust/mlt/tests/mlt_decoder_test.rs new file mode 100644 index 00000000..e69de29b From a9e618a941acdde19dd363ccbb3ff1b8bb4073d3 Mon Sep 17 00:00:00 2001 From: Frank Jimenez Date: Sun, 16 Feb 2025 22:01:11 +0000 Subject: [PATCH 6/7] chore: remove data dir --- rust/mlt/src/data/mod.rs | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 rust/mlt/src/data/mod.rs diff --git a/rust/mlt/src/data/mod.rs b/rust/mlt/src/data/mod.rs deleted file mode 100644 index 444c3c6f..00000000 --- a/rust/mlt/src/data/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -// public record Feature(long id, Geometry geometry, Map properties) {} - -// #[derive(Debug)] -// pub enum PropertyValue { -// String(String), -// Integer(i64), -// Float(f64), -// Boolean(bool), -// List(Vec), -// } From 2e34531e75bfe90b09c8309ae490382bdf4c1d8f Mon Sep 17 00:00:00 2001 From: Frank Jimenez Date: Thu, 20 Feb 2025 21:03:54 +0000 Subject: [PATCH 7/7] fix: remove data mod --- rust/mlt/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rust/mlt/src/lib.rs b/rust/mlt/src/lib.rs index efd2b838..8bd9497b 100644 --- a/rust/mlt/src/lib.rs +++ b/rust/mlt/src/lib.rs @@ -1,6 +1,5 @@ mod error; mod converter; -mod data; mod metadata; pub use error::MltResult;