From f7b3f20dec5e81f6e5d3507204669129c4645a63 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Sat, 12 Oct 2024 19:12:20 +0200 Subject: [PATCH 1/4] Adding a simple persistence provider Signed-off-by: Sebastian Schildt Added hint for building to the readme format cargo file --- .gitignore | 1 + kuksa-persistence-provider/Cargo.lock | 1530 +++++++++++++++++ kuksa-persistence-provider/Cargo.toml | 31 + kuksa-persistence-provider/Readme.md | 100 ++ kuksa-persistence-provider/config.json | 25 + .../src/kuksaconnector.rs | 456 +++++ kuksa-persistence-provider/src/main.rs | 444 +++++ kuksa-persistence-provider/src/storage.rs | 64 + .../src/storage/filestorage.rs | 229 +++ kuksa-persistence-provider/statestore.json | 20 + 10 files changed, 2900 insertions(+) create mode 100644 .gitignore create mode 100644 kuksa-persistence-provider/Cargo.lock create mode 100644 kuksa-persistence-provider/Cargo.toml create mode 100644 kuksa-persistence-provider/Readme.md create mode 100644 kuksa-persistence-provider/config.json create mode 100644 kuksa-persistence-provider/src/kuksaconnector.rs create mode 100644 kuksa-persistence-provider/src/main.rs create mode 100644 kuksa-persistence-provider/src/storage.rs create mode 100644 kuksa-persistence-provider/src/storage/filestorage.rs create mode 100644 kuksa-persistence-provider/statestore.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0da3ea9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +kuksa-persistence-provider/target/* diff --git a/kuksa-persistence-provider/Cargo.lock b/kuksa-persistence-provider/Cargo.lock new file mode 100644 index 0000000..512d268 --- /dev/null +++ b/kuksa-persistence-provider/Cargo.lock @@ -0,0 +1,1530 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "autotools" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef941527c41b0fc0dd48511a8154cd5fc7e29200a0ff8b7203c5d777dbc795cf" +dependencies = [ + "cc", +] + +[[package]] +name = "axum" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core", + "bitflags 1.3.2", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" + +[[package]] +name = "cc" +version = "1.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +dependencies = [ + "shlex", +] + +[[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.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "djson" +version = "0.1.0" +dependencies = [ + "tinyjson", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[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.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "kuksa" +version = "0.4.4" +source = "git+https://github.com/eclipse-kuksa/kuksa-databroker.git?branch=feature/refactor_kuksa_crate#f31e2f27a92a4d7cde90342b3a5eb5f6630db71b" +dependencies = [ + "http", + "kuksa-grpc", + "kuksa-proto", + "thiserror", + "tokio", + "tokio-stream", + "tonic", +] + +[[package]] +name = "kuksa-grpc" +version = "0.4.4" +source = "git+https://github.com/eclipse-kuksa/kuksa-databroker.git?branch=feature/refactor_kuksa_crate#f31e2f27a92a4d7cde90342b3a5eb5f6630db71b" +dependencies = [ + "http", + "tokio", + "tokio-stream", + "tonic", +] + +[[package]] +name = "kuksa-persistence-provider" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "djson", + "env_logger", + "kuksa", + "log", + "prost-types", + "regex", + "tempfile", + "tinyjson", + "tokio", +] + +[[package]] +name = "kuksa-proto" +version = "0.4.1" +source = "git+https://github.com/eclipse-kuksa/kuksa-databroker.git?branch=feature/refactor_kuksa_crate#f31e2f27a92a4d7cde90342b3a5eb5f6630db71b" +dependencies = [ + "prost", + "prost-types", + "protobuf-src", + "tonic", + "tonic-build", +] + +[[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.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap 2.6.0", +] + +[[package]] +name = "pin-project" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[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.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +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 0.4.1", + "itertools", + "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", + "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 = "protobuf-src" +version = "1.1.0+21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7ac8852baeb3cc6fb83b93646fb93c0ffe5d14bf138c945ceb4b9948ee0e3c1" +dependencies = [ + "autotools", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +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.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags 2.6.0", +] + +[[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.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +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 = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "serde" +version = "1.0.213" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.213" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[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.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[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.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "tinyjson" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ab95735ea2c8fd51154d01e39cf13912a78071c2d89abc49a7ef102a7dd725a" + +[[package]] +name = "tokio" +version = "1.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tonic" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64", + "bytes", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "rustls-pemfile", + "tokio", + "tokio-rustls", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[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.85", +] + +[[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 = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[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.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[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 = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] diff --git a/kuksa-persistence-provider/Cargo.toml b/kuksa-persistence-provider/Cargo.toml new file mode 100644 index 0000000..9ec9425 --- /dev/null +++ b/kuksa-persistence-provider/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "kuksa-persistence-provider" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "4.5.20", features = ["derive"] } +tinyjson = {version = "2.5.1", optional = true } +kuksa = { git = "https://github.com/eclipse-kuksa/kuksa-databroker.git", branch = "feature/refactor_kuksa_crate", package = "kuksa" } +log = "0.4.22" +env_logger = "0.11.5" +regex = "1.11.0" +anyhow = "1.0.40" +#Only this version is compatible with kuksa crate. 0.13 is not +prost-types = "0.11.9" +tokio = { version="1.40.0", features = ["full"] } + +# TODO: change this to a a github path once available +djson = { path="../../platform/modules/json-al/djson_rust/" , optional = true } + +# For testing +[dev_dependencies] +tempfile = "3.2.0" + +[features] +default = ["json_tinyjson"] +# use a dependable json library, this still requires tiny-json for writing +json_djson = [ "dep:djson","dep:tinyjson" ] +json_tinyjson = [ "dep:tinyjson" ] diff --git a/kuksa-persistence-provider/Readme.md b/kuksa-persistence-provider/Readme.md new file mode 100644 index 0000000..4185689 --- /dev/null +++ b/kuksa-persistence-provider/Readme.md @@ -0,0 +1,100 @@ +# KUKSA Persistence Provider + +All data in KUKSA is ephemeral. However, in a car there is often data that does not change over the lifetime of a vehicle, and data where you want changes to be persisted over ignition cycles. + +This provider can achieve this. It can restore certain values upon startup, either sensor (current) values, or actuations. + +An example for one-time restoration of current values are attributes that are maybe not set in a default VSS model deployed to ALL cars of a specific variant, but nevertheless are constant of a specific car, such as the VIN or the Vehicle Color. + +This provider can also watch (subscribe) certain current or actuation values. This is useful when interacting with components that do not provide their own persistence management. Assume a climate control UI that can react on user input and interact with the HVAC system, but is otherwise stateless. By watching and restoring the desired target temperature, the user's preference is saved and restored, without the HVAC UI needing any specific code to handle this. + +## Configuration: config.json + +Main configuration is in config.json, and example may look like this + +```json +{ + "restore-only": { + "values": [ + "Vehicle.VehicleIdentification.VIN", + "Vehicle.VehicleIdentification.VehicleInteriorColor" + ], + "actuators": [ + "Vehicle.Cabin.Infotainment.HMI.TemperatureUnit" + ] + }, + + "restore-and-watch": { + "values": [ + "Vehicle.Cabin.Infotainment.HMI.TemperatureUnit", + "Vehicle.Cabin.HVAC.Station.Row4.Passenger.FanSpeed" + ], + "actuators": [ + "Vehicle.Cabin.Infotainment.Media.Volume" + ] + }, + "state-storage": { + "type": "file", + "path": "statestore.json" + } +} +``` + +### section restore-only + +These elements will be restored from the state store upon startup, but their values will not be watched and updated for changes. You can define whether the current values (values) will be restored or whether a target value is set (actuators). + +### section restore-and-watch + +These elements will be restored from the state store upon startup. It is the intention to also monitor their state and update it in the state store. You can define whether the current values (values) will be restored and watched or whether a target value is set (actuators) and watched. As restore-and-watch includes restore, there is no need to add paths in restore-and-watch to restore-only as well. + +## state-storage + +Configures the state sotrage used to retrieve values. Currently supported: file + +## File storage: statestore.json + +This is a valid state store for the file storage. +*Note: ALl VALUES NEED TO BE STORED AS STRING*. +As the statestore does not make a difference between current and target (actuation) values it is currently not possible to watch or restore both for a single VSS path. + +```json + +{ + "Vehicle.VehicleIdentification.VIN": { + "value": "DEADBEEF" + }, + "Vehicle.VehicleIdentification.VehicleInteriorColor": { + "value": "Black" + } +} +``` + +## Features + +* djson: Use a dependable json library. + Check out the repo with the depenable json library at the same level as the parent folder or project folder of this repo. + Enable with ```cargo build --features json_djson --no-default-features``` + + +## Build + +```bash +cargo build --features json_djson --no-default-features +``` + +## Test + +Start kuksa databroker with: + +```bash +docker run -it --rm --net=host ghcr.io/eclipse-kuksa/kuksa-databroker:latest --port 55556 +``` + +Start kuksa sdk with: + +```bash +docker run -it --rm --net=host ghcr.io/eclipse-kuksa/kuksa-python-sdk/kuksa-client:latest grpc://127.0.0.1:55556 +# Check Vales in cmd +getValue Vehicle.Cabin.HVAC.Station.Row4.Passenger.FanSpeed +``` diff --git a/kuksa-persistence-provider/config.json b/kuksa-persistence-provider/config.json new file mode 100644 index 0000000..28cda7d --- /dev/null +++ b/kuksa-persistence-provider/config.json @@ -0,0 +1,25 @@ +{ + "restore-only": { + "values": [ + "Vehicle.VehicleIdentification.VIN", + "Vehicle.VehicleIdentification.VehicleInteriorColor" + ], + "actuators": [ + "Vehicle.Cabin.Infotainment.HMI.TemperatureUnit" + ] + }, + + "restore-and-watch": { + "values": [ + "Vehicle.Cabin.Infotainment.HMI.TemperatureUnit", + "Vehicle.Cabin.HVAC.Station.Row4.Passenger.FanSpeed" + ], + "actuators": [ + "Vehicle.Cabin.Infotainment.Media.Volume" + ] + }, + "state-storage": { + "type": "file", + "path": "statestore.json" + } +} \ No newline at end of file diff --git a/kuksa-persistence-provider/src/kuksaconnector.rs b/kuksa-persistence-provider/src/kuksaconnector.rs new file mode 100644 index 0000000..9d51d05 --- /dev/null +++ b/kuksa-persistence-provider/src/kuksaconnector.rs @@ -0,0 +1,456 @@ +/******************************************************************************** +* Copyright (c) 2024 Contributors to the Eclipse Foundation +* +* This program and the accompanying materials are made available under the +* terms of the Apache License 2.0 which is available at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* SPDX-License-Identifier: Apache-2.0 +********************************************************************************/ + +use std::collections::HashMap; +use std::fmt; +use std::sync::mpsc::Sender; +use std::sync::{Arc, Mutex}; +use std::time::SystemTime; + +use kuksa::proto; + +use crate::storage::{self, StoreItem}; + +#[derive(Debug)] +pub struct ParseError {} + +pub fn create_kuksa_client(uri: &str) -> Arc> { + log::info!("Creating Kuksa Databroker client for URI: {}", uri); + let uri = kuksa::Uri::try_from(uri).expect("Invalid URI for Kuksa Databroker connection."); + Arc::new(Mutex::new(kuksa::Client::new(uri))) +} + +pub async fn get_from_storage_and_set_values( + storage: &impl storage::Storage, + kuksa_client: &Arc>, + vsspaths: &Vec, +) { + for vsspath in vsspaths { + get_from_storage_and_set(storage, kuksa_client, vsspath, false).await; + } +} + +pub async fn get_from_storage_and_set_actuations( + storage: &impl storage::Storage, + kuksa_client: &Arc>, + vsspaths: &Vec, +) { + for vsspath in vsspaths { + get_from_storage_and_set(storage, kuksa_client, vsspath, true).await; + } +} + +pub async fn get_from_storage_and_set( + storage: &impl storage::Storage, + kuksa_client: &Arc>, + vsspath: &str, + is_actuator: bool, +) { + log::debug!("Query storage for VSS signal: {}", vsspath); + let value = match storage.get(vsspath) { + Some(x) => x, + None => { + log::warn!("No value for VSS signal: {} stored", vsspath); + return; + } + }; + + //Figure out metadata: + let datapoint_entries = match kuksa_client + .lock() + .unwrap() + .get_metadata(vec![vsspath]) + .await + { + Ok(data_entries) => Some(data_entries), + Err(kuksa::Error::Status(status)) => { + log::warn!( + "Error: Could not get metadata for VSS signal: {}, Status: {}", + vsspath, + &status + ); + None + } + Err(kuksa::Error::Connection(msg)) => { + log::warn!( + "Connection Error: Could not get metadata for VSS signal: {}, Reason: {}", + vsspath, + &msg + ); + None + } + Err(kuksa::Error::Function(msg)) => { + log::warn!( + "Error: Could not get metadata for VSS signal: {}, Errors: {msg:?}", + vsspath + ); + None + } + }; + + if datapoint_entries.is_none() { + return; + } + + /* We can only have one match, as we query only one path (user entering branch + * in config is considered dumb) */ + if let Some(entries) = datapoint_entries { + if let Some(metadata) = &entries.first().unwrap().metadata { + let data_value = try_into_data_value( + value, + proto::v1::DataType::from_i32(metadata.data_type).unwrap(), + ); + if data_value.is_err() { + log::warn!( + "Could not parse \"{}\" as {:?}", + value, + proto::v1::DataType::from_i32(metadata.data_type).unwrap() + ); + return; + } + + let ts = prost_types::Timestamp::from(SystemTime::now()); + let datapoints = HashMap::from([( + vsspath.to_string().clone(), + proto::v1::Datapoint { + timestamp: Some(ts), + value: Some(data_value.unwrap()), + }, + )]); + + let result = { + if is_actuator { + kuksa_client + .lock() + .unwrap() + .set_target_values(datapoints) + .await + } else { + kuksa_client + .lock() + .unwrap() + .set_current_values(datapoints) + .await + } + }; + + match result { + Ok(_) => { + log::debug!("Succes setting {} to {}", vsspath, value); + } + Err(kuksa::Error::Status(status)) => { + log::warn!( + "Error: Could not set value for VSS signal: {}, Status: {}", + vsspath, + &status + ); + } + Err(kuksa::Error::Connection(msg)) => { + log::warn!( + "Connection Error: Could not set value for VSS signal: {}, Reason: {}", + vsspath, + &msg + ); + } + Err(kuksa::Error::Function(msg)) => { + log::warn!( + "Error: Could not set value for VSS signal: {}, Errors: {msg:?}", + vsspath + ); + } + }; + } + } +} + +pub async fn watch_values( + storage_queue: Sender, + kuksa_client: &Arc>, + vsspaths: Vec<&str>, + is_actuator: bool, +) { + log::info!( + "Subscribing to {} for VSS signals: {:?}", + { + match is_actuator { + true => "actuators", + false => "current values", + } + }, + &vsspaths + ); + + let res = match is_actuator { + true => { + kuksa_client + .lock() + .unwrap() + .subscribe_target_values(vsspaths) + .await + } + false => { + kuksa_client + .lock() + .unwrap() + .subscribe_current_values(vsspaths) + .await + } + }; + match res { + Ok(mut subs) => { + tokio::spawn(async move { + loop { + match subs.message().await { + Ok(resp) => { + if let Some(r) = resp { + for update in r.updates { + if let Some(entry) = update.entry { + let newdp = match is_actuator { + true => entry.actuator_target, + false => entry.value, + }; + if let Some(datapoint) = newdp { + let data = DisplayDatapoint(datapoint); + log::info!( + "Received value {} for VSS signal {}", + data.to_string(), + entry.path + ); + + match storage_queue.send(StoreItem { + path: entry.path.clone(), + value: data.to_string(), + }) { + Ok(_) => {} + Err(err) => { + log::warn!( + "Error sending data to storage {:?}", + err + ); + } + } + } + } + } + } + } + Err(err) => { + log::warn!("Error: Could not receive message: {:?}", err); + break; + } + } + } + }); + } + Err(err) => { + log::warn!("Error: Could not subscribe to VSS signals: {:?}", err); + } + } +} + +/* Donation from databroker-cli */ +fn try_into_data_value( + input: &str, + data_type: proto::v1::DataType, +) -> Result { + if input == "NotAvailable" { + return Ok(proto::v1::datapoint::Value::String(input.to_string())); + } + + match data_type { + proto::v1::DataType::String => Ok(proto::v1::datapoint::Value::String(input.to_owned())), + proto::v1::DataType::StringArray => match get_array_from_input(input.to_owned()) { + Ok(value) => Ok(proto::v1::datapoint::Value::StringArray( + proto::v1::StringArray { values: value }, + )), + Err(err) => Err(err), + }, + proto::v1::DataType::Boolean => match input.parse::() { + Ok(value) => Ok(proto::v1::datapoint::Value::Bool(value)), + Err(_) => Err(ParseError {}), + }, + proto::v1::DataType::BooleanArray => match get_array_from_input(input.to_owned()) { + Ok(value) => Ok(proto::v1::datapoint::Value::BoolArray( + proto::v1::BoolArray { values: value }, + )), + Err(err) => Err(err), + }, + proto::v1::DataType::Int8 => match input.parse::() { + Ok(value) => Ok(proto::v1::datapoint::Value::Int32(value as i32)), + Err(_) => Err(ParseError {}), + }, + proto::v1::DataType::Int8Array => match get_array_from_input(input.to_owned()) { + Ok(value) => Ok(proto::v1::datapoint::Value::Int32Array( + proto::v1::Int32Array { values: value }, + )), + Err(err) => Err(err), + }, + proto::v1::DataType::Int16 => match input.parse::() { + Ok(value) => Ok(proto::v1::datapoint::Value::Int32(value as i32)), + Err(_) => Err(ParseError {}), + }, + proto::v1::DataType::Int16Array => match get_array_from_input(input.to_owned()) { + Ok(value) => Ok(proto::v1::datapoint::Value::Int32Array( + proto::v1::Int32Array { values: value }, + )), + Err(err) => Err(err), + }, + proto::v1::DataType::Int32 => match input.parse::() { + Ok(value) => Ok(proto::v1::datapoint::Value::Int32(value)), + Err(_) => Err(ParseError {}), + }, + proto::v1::DataType::Int32Array => match get_array_from_input(input.to_owned()) { + Ok(value) => Ok(proto::v1::datapoint::Value::Int32Array( + proto::v1::Int32Array { values: value }, + )), + Err(err) => Err(err), + }, + proto::v1::DataType::Int64 => match input.parse::() { + Ok(value) => Ok(proto::v1::datapoint::Value::Int64(value)), + Err(_) => Err(ParseError {}), + }, + proto::v1::DataType::Int64Array => match get_array_from_input(input.to_owned()) { + Ok(value) => Ok(proto::v1::datapoint::Value::Int64Array( + proto::v1::Int64Array { values: value }, + )), + Err(err) => Err(err), + }, + proto::v1::DataType::Uint8 => match input.parse::() { + Ok(value) => Ok(proto::v1::datapoint::Value::Uint32(value as u32)), + Err(_) => Err(ParseError {}), + }, + proto::v1::DataType::Uint8Array => match get_array_from_input(input.to_owned()) { + Ok(value) => Ok(proto::v1::datapoint::Value::Uint32Array( + proto::v1::Uint32Array { values: value }, + )), + Err(err) => Err(err), + }, + proto::v1::DataType::Uint16 => match input.parse::() { + Ok(value) => Ok(proto::v1::datapoint::Value::Uint32(value as u32)), + Err(_) => Err(ParseError {}), + }, + proto::v1::DataType::Uint16Array => match get_array_from_input(input.to_owned()) { + Ok(value) => Ok(proto::v1::datapoint::Value::Uint32Array( + proto::v1::Uint32Array { values: value }, + )), + Err(err) => Err(err), + }, + proto::v1::DataType::Uint32 => match input.parse::() { + Ok(value) => Ok(proto::v1::datapoint::Value::Uint32(value)), + Err(_) => Err(ParseError {}), + }, + proto::v1::DataType::Uint32Array => match get_array_from_input(input.to_owned()) { + Ok(value) => Ok(proto::v1::datapoint::Value::Uint32Array( + proto::v1::Uint32Array { values: value }, + )), + Err(err) => Err(err), + }, + proto::v1::DataType::Uint64 => match input.parse::() { + Ok(value) => Ok(proto::v1::datapoint::Value::Uint64(value)), + Err(_) => Err(ParseError {}), + }, + proto::v1::DataType::Uint64Array => match get_array_from_input(input.to_owned()) { + Ok(value) => Ok(proto::v1::datapoint::Value::Uint64Array( + proto::v1::Uint64Array { values: value }, + )), + Err(err) => Err(err), + }, + proto::v1::DataType::Float => match input.parse::() { + Ok(value) => Ok(proto::v1::datapoint::Value::Float(value)), + Err(_) => Err(ParseError {}), + }, + proto::v1::DataType::FloatArray => match get_array_from_input(input.to_owned()) { + Ok(value) => Ok(proto::v1::datapoint::Value::FloatArray( + proto::v1::FloatArray { values: value }, + )), + Err(err) => Err(err), + }, + proto::v1::DataType::Double => match input.parse::() { + Ok(value) => Ok(proto::v1::datapoint::Value::Double(value)), + Err(_) => Err(ParseError {}), + }, + proto::v1::DataType::DoubleArray => match get_array_from_input(input.to_owned()) { + Ok(value) => Ok(proto::v1::datapoint::Value::DoubleArray( + proto::v1::DoubleArray { values: value }, + )), + Err(err) => Err(err), + }, + _ => Err(ParseError {}), + } +} + +pub fn get_array_from_input(values: String) -> Result, ParseError> { + let raw_input = values + .strip_prefix('[') + .and_then(|s| s.strip_suffix(']')) + .ok_or(ParseError {})?; + + let pattern = r#"(?:\\.|[^",])*"(?:\\.|[^"])*"|[^",]+"#; + + let regex = regex::Regex::new(pattern).unwrap(); + let inputs = regex.captures_iter(raw_input); + + let mut array: Vec = vec![]; + for part in inputs { + match part[0] + .trim() + .replace('\"', "") + .replace('\\', "\"") + .parse::() + { + Ok(value) => array.push(value), + Err(_) => return Err(ParseError {}), + } + } + Ok(array) +} + +struct DisplayDatapoint(proto::v1::Datapoint); + +fn display_array(f: &mut fmt::Formatter<'_>, array: &[T]) -> fmt::Result +where + T: fmt::Display, +{ + f.write_str("[")?; + let real_delimiter = ", "; + let mut delimiter = ""; + for value in array { + write!(f, "{delimiter}")?; + delimiter = real_delimiter; + write!(f, "{value}")?; + } + f.write_str("]") +} + +impl fmt::Display for DisplayDatapoint { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match &self.0.value { + Some(value) => match value { + proto::v1::datapoint::Value::Bool(value) => f.pad(&format!("{value}")), + proto::v1::datapoint::Value::Int32(value) => f.pad(&format!("{value}")), + proto::v1::datapoint::Value::Int64(value) => f.pad(&format!("{value}")), + proto::v1::datapoint::Value::Uint32(value) => f.pad(&format!("{value}")), + proto::v1::datapoint::Value::Uint64(value) => f.pad(&format!("{value}")), + proto::v1::datapoint::Value::Float(value) => f.pad(&format!("{value:.2}")), + proto::v1::datapoint::Value::Double(value) => f.pad(&format!("{value}")), + proto::v1::datapoint::Value::String(value) => f.pad(&value.to_owned()), + proto::v1::datapoint::Value::StringArray(array) => display_array(f, &array.values), + proto::v1::datapoint::Value::BoolArray(array) => display_array(f, &array.values), + proto::v1::datapoint::Value::Int32Array(array) => display_array(f, &array.values), + proto::v1::datapoint::Value::Int64Array(array) => display_array(f, &array.values), + proto::v1::datapoint::Value::Uint32Array(array) => display_array(f, &array.values), + proto::v1::datapoint::Value::Uint64Array(array) => display_array(f, &array.values), + proto::v1::datapoint::Value::FloatArray(array) => display_array(f, &array.values), + proto::v1::datapoint::Value::DoubleArray(array) => display_array(f, &array.values), + }, + None => f.pad("None"), + } + } +} diff --git a/kuksa-persistence-provider/src/main.rs b/kuksa-persistence-provider/src/main.rs new file mode 100644 index 0000000..0b20c8d --- /dev/null +++ b/kuksa-persistence-provider/src/main.rs @@ -0,0 +1,444 @@ +/******************************************************************************** +* Copyright (c) 2024 Contributors to the Eclipse Foundation +* +* This program and the accompanying materials are made available under the +* terms of the Apache License 2.0 which is available at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* SPDX-License-Identifier: Apache-2.0 +********************************************************************************/ + +mod kuksaconnector; +mod storage; + +use storage::Storage; + +use anyhow::{anyhow, Result}; +use clap::Parser; +use std::collections::HashMap; +use std::fmt::Debug; +use std::{env, path::PathBuf}; + +// Ensure no unsafe code is used +#[forbid(unsafe_code)] +// Use one of two JSON libraries +#[cfg(all(feature = "json_tinyjson", feature = "json_djson"))] +compile_error!( + "feature \"json_tinyjson\" and feature \"json_djson\" cannot be enabled at the same time" +); + +#[cfg(feature = "json_tinyjson")] +use tinyjson::JsonValue; + +#[cfg(feature = "json_djson")] +use djson::Value as JsonValue; + +use tokio::signal::ctrl_c; + +#[derive(Debug, Clone, PartialEq)] +enum ConfigValue { + Number(f64), + Boolean(bool), + String(String), + Null, + Array(Vec), + Object(HashMap), +} + +// Convert from JSON value (depending on the feature) to ConfigValue +impl From for ConfigValue { + fn from(value: JsonValue) -> Self { + match value { + JsonValue::Null => ConfigValue::Null, + JsonValue::Boolean(b) => ConfigValue::Boolean(b), + JsonValue::Number(n) => ConfigValue::Number(n), + JsonValue::String(s) => ConfigValue::String(s), + JsonValue::Array(a) => ConfigValue::Array(a.into_iter().map(Into::into).collect()), + JsonValue::Object(o) => { + ConfigValue::Object(o.into_iter().map(|(k, v)| (k, v.into())).collect()) + } + } + } +} + +#[derive(Parser)] +#[command(version, about, long_about = None)] +struct CmdLine { + /// JSON file containing the configuration + #[arg(short, long, value_name = "FILE")] + config: Option, + + /// Turn debugging information on + #[arg(short, long, action = clap::ArgAction::Count)] + debug: u8, +} + +// Parse the configuration file to a ConfigValue +// The configuration file is expected to be in JSON format +fn parse_cfgfile(path: &PathBuf) -> Result { + let config_str = std::fs::read_to_string(&path)?; + + log::debug!("Configuration file content: {}", config_str); + + #[cfg(feature = "json_tinyjson")] + let parsed_cfg: ConfigValue = config_str.parse::()?.into(); + + #[cfg(feature = "json_djson")] + let parsed_cfg: ConfigValue = djson::from_reader(config_str.as_bytes())?; + + Ok(parsed_cfg) +} + +// Create a storage instance from the configuration +fn create_storage_from_cfg(parsed_cfg: &ConfigValue) -> Result { + let parsed_cfg_hash = match parsed_cfg { + ConfigValue::Object(o) => o, + _ => { + return Err(anyhow!("Error: JSON config data structure is wrong")); + } + }; + + log::debug!("Parsed JSON data structure: {:?}", parsed_cfg_hash); + + let parsed_storage_type: storage::StorageType = match parsed_cfg_hash["state-storage"] { + ConfigValue::Object(ref parsed_storage_config) => { + match parsed_storage_config.get("type") { + // For FileStorageType + Some(ConfigValue::String(s)) if *s == "file".to_string() => { + // FileStorageType needs filepath otherwise default is + match parsed_storage_config.get("path") { + Some(ConfigValue::String(path)) => { + storage::StorageType::FileStorageType(storage::FileStorageType { + filepath: path.clone(), + }) + } + None => { + log::info!( + "state storage path is not existent, using default storage path" + ); + storage::StorageType::FileStorageType( + storage::FileStorageType::default(), + ) + } + _ => { + log::error!("Error: state storage path is invalid"); + std::process::exit(1); + } + } + } + None => { + log::info!("no state storage type found, using default"); + storage::StorageType::default() + } + // Undefined storage types + _ => { + return Err(anyhow!("Error: state storage type is invalid")); + } + } + } + _ => { + log::info!("no state storage configuration found, using default"); + storage::StorageType::default() + } + }; + + Ok(storage::FileStorage::new(storage::StorageConfig { + storagetype: parsed_storage_type, + })) +} + +fn collect_vss_paths( + config: &ConfigValue, + section_name: &str, + element_name: &str, + str_arrays: &mut [&mut Vec], +) { + let parsed_cfg_hash = match config { + ConfigValue::Object(o) => o, + _ => { + log::error!("Error: JSON config data structure is wrong"); + std::process::exit(1); + } + }; + // Find section in parsed config + match parsed_cfg_hash.get(section_name) { + Some(ConfigValue::Object(section)) => { + match section.get(element_name) { + Some(ConfigValue::Array(elements)) => { + for path in elements { + match path { + ConfigValue::String(vsspath) => { + // restore_current_values.push(vsspath.clone()); + for str_array in str_arrays.iter_mut() { + str_array.push(vsspath.clone()); + } + } + _ => { + log::info!("invalid {} {} found", section_name, element_name); + } + } + } + } + _ => { + log::info!("no {} {} found", section_name, element_name); + } + } + } + None => { + log::info!("no {} configuration found", section_name); + } + _ => { + log::info!("invalid {} configuration found", section_name); + } + } +} + +#[tokio::main] +async fn main() { + // Initialize logger + if env::var("RUST_LOG").is_err() { + env::set_var("RUST_LOG", "info") + } + env_logger::init(); + + let args = CmdLine::parse(); + + let config_path = args.config.unwrap_or_else(|| PathBuf::from("config.json")); + + let parsed_cfg = match parse_cfgfile(&config_path) { + Ok(cfg) => cfg, + Err(e) => { + log::error!("Error parsing configuration file: {}", e); + std::process::exit(1); + } + }; + let storage = match create_storage_from_cfg(&parsed_cfg) { + Ok(s) => s, + Err(e) => { + log::error!("Error creating storage: {}", e); + std::process::exit(1); + } + }; + + let mut restore_current_values: Vec = vec![]; + let mut restore_actuation_values: Vec = vec![]; + let mut watch_current_values: Vec = vec![]; + let mut watch_actuation_values: Vec = vec![]; + + collect_vss_paths( + &parsed_cfg, + "restore-only", + "values", + &mut [&mut restore_current_values], + ); + collect_vss_paths( + &parsed_cfg, + "restore-only", + "actuators", + &mut [&mut restore_actuation_values], + ); + + collect_vss_paths( + &parsed_cfg, + "restore-and-watch", + "values", + &mut [&mut restore_current_values, &mut watch_current_values], + ); + collect_vss_paths( + &parsed_cfg, + "restore-and-watch", + "actuators", + &mut [&mut restore_actuation_values, &mut watch_actuation_values], + ); + + // Each subscription needs a separate client + let kuksa_client = kuksaconnector::create_kuksa_client("grpc://127.0.01:55556"); + let kuksa_client2 = kuksaconnector::create_kuksa_client("grpc://127.0.01:55556"); + + kuksaconnector::get_from_storage_and_set_values( + &storage, + &kuksa_client, + &restore_current_values, + ) + .await; + kuksaconnector::get_from_storage_and_set_actuations( + &storage, + &kuksa_client, + &restore_actuation_values, + ) + .await; + + kuksaconnector::watch_values( + storage.get_queue(), + &kuksa_client, + watch_current_values.iter().map(|s| &**s).collect(), + false, + ) + .await; + kuksaconnector::watch_values( + storage.get_queue(), + &kuksa_client2, + watch_actuation_values.iter().map(|s| &**s).collect(), + true, + ) + .await; + + tokio::select! { + _ = ctrl_c() => { + println!("Received Ctrl+C, exiting."); + return; + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::fs::File; + use std::io::Write; + use tempfile::tempdir; + + #[test] + fn test_parse_cfgfile_valid_json_simple() { + let dir = tempdir().unwrap(); + let file_path = dir.path().join("config.json"); + let mut file = File::create(&file_path).unwrap(); + writeln!(file, r#"{{"key": "value"}}"#).unwrap(); + + let config = parse_cfgfile(&file_path).unwrap(); + match config { + ConfigValue::Object(ref obj) => { + assert_eq!( + obj.get("key"), + Some(&ConfigValue::String("value".to_string())) + ); + } + _ => panic!("Parsed config is not an object"), + } + } + + #[test] + fn test_parse_cfgfile_valid_cfg() { + let dir = tempdir().unwrap(); + let file_path = dir.path().join("config.json"); + let mut file = File::create(&file_path).unwrap(); + let test_json_string = r#" + { + "restore-only": { + "values": [ + "Vehicle.VehicleIdentification.VIN", + "Vehicle.VehicleIdentification.VehicleInteriorColor" + ], + "actuators": [ + "Vehicle.Cabin.Infotainment.HMI.TemperatureUnit" + ] + } + } + "#; + + writeln!(file, "{}", test_json_string).unwrap(); + let config = parse_cfgfile(&file_path).unwrap(); + match config { + ConfigValue::Object(ref obj) => { + assert_eq!( + obj.get("restore-only"), + Some(&ConfigValue::Object({ + let mut map = HashMap::new(); + map.insert( + "values".to_string(), + ConfigValue::Array(vec![ + ConfigValue::String( + "Vehicle.VehicleIdentification.VIN".to_string(), + ), + ConfigValue::String( + "Vehicle.VehicleIdentification.VehicleInteriorColor" + .to_string(), + ), + ]), + ); + map.insert( + "actuators".to_string(), + ConfigValue::Array(vec![ConfigValue::String( + "Vehicle.Cabin.Infotainment.HMI.TemperatureUnit".to_string(), + )]), + ); + map + })) + ); + } + _ => panic!("Parsed config is not an object"), + } + } + + #[test] + fn test_parse_cfgfile_invalid_json_1() { + let dir = tempdir().unwrap(); + let file_path = dir.path().join("config.json"); + let mut file = File::create(&file_path).unwrap(); + writeln!(file, r#"{{"key" "value"}}"#).unwrap(); // Invalid JSON + + let result = parse_cfgfile(&file_path); + assert!(result.is_err()); + } + + #[test] + fn test_parse_cfgfile_invalid_json_unexpeof() { + let dir = tempdir().unwrap(); + let file_path = dir.path().join("config.json"); + let mut file = File::create(&file_path).unwrap(); + let test_json_string = r#"{{"key" "value"}"#; + writeln!(file, "{}", test_json_string).unwrap(); + + let result = parse_cfgfile(&file_path); + assert!(result.is_err()); + } + + #[test] + fn test_create_storage_from_cfg_nofile() { + let dir = tempdir().unwrap(); + let file_path = dir.path().join("config.json"); + let mut file = File::create(&file_path).unwrap(); + writeln!(file, r#"{{"key": "value"}}"#).unwrap(); // Invalid JSON + let mut config = HashMap::new(); + let mut storage_config = HashMap::new(); + storage_config.insert("type".to_string(), ConfigValue::String("file".to_string())); + storage_config.insert( + "path".to_string(), + ConfigValue::String(file_path.to_str().unwrap().to_string()), + ); + config.insert( + "state-storage".to_string(), + ConfigValue::Object(storage_config), + ); + + let storage = create_storage_from_cfg(&ConfigValue::Object(config)); + assert!(storage.is_ok()); + } + + #[test] + fn test_collect_vss_paths() { + let mut config = HashMap::new(); + let mut section = HashMap::new(); + section.insert( + "values".to_string(), + ConfigValue::Array(vec![ + ConfigValue::String("path1".to_string()), + ConfigValue::String("path2".to_string()), + ]), + ); + config.insert("restore-only".to_string(), ConfigValue::Object(section)); + + let mut restore_current_values: Vec = vec![]; + collect_vss_paths( + &ConfigValue::Object(config), + "restore-only", + "values", + &mut [&mut restore_current_values], + ); + + assert_eq!( + restore_current_values, + vec!["path1".to_string(), "path2".to_string()] + ); + } +} diff --git a/kuksa-persistence-provider/src/storage.rs b/kuksa-persistence-provider/src/storage.rs new file mode 100644 index 0000000..35f9fa7 --- /dev/null +++ b/kuksa-persistence-provider/src/storage.rs @@ -0,0 +1,64 @@ +/******************************************************************************** +* Copyright (c) 2024 Contributors to the Eclipse Foundation +* +* This program and the accompanying materials are made available under the +* terms of the Apache License 2.0 which is available at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* SPDX-License-Identifier: Apache-2.0 +********************************************************************************/ + +pub mod filestorage; + +use std::sync::mpsc::Sender; + +pub use filestorage::FileStorage; + +#[derive(Debug)] +pub struct StoreItem { + pub path: String, + pub value: String, +} + +#[derive(Default, Debug, PartialEq)] +pub struct StorageConfig { + pub storagetype: StorageType, +} + +#[derive(Debug, PartialEq)] +#[non_exhaustive] +pub enum StorageType { + FileStorageType(FileStorageType), + // Add more storage types here +} + +#[derive(Debug, PartialEq)] +pub struct FileStorageType { + pub filepath: String, +} + +impl Default for StorageType { + fn default() -> Self { + StorageType::FileStorageType(FileStorageType::default()) + } +} + +impl Default for FileStorageType { + fn default() -> Self { + FileStorageType { + filepath: "storage.json".to_string(), + } + } +} + +pub trait Storage { + fn new(config: StorageConfig) -> Self + where + Self: Sized; + + fn get(&self, vsspath: &str) -> Option<&str>; + + fn set(&self, vsspath: &str, vssvalue: &str) -> Result<(), ()>; + + fn get_queue(&self) -> Sender; +} diff --git a/kuksa-persistence-provider/src/storage/filestorage.rs b/kuksa-persistence-provider/src/storage/filestorage.rs new file mode 100644 index 0000000..c9be42a --- /dev/null +++ b/kuksa-persistence-provider/src/storage/filestorage.rs @@ -0,0 +1,229 @@ +/******************************************************************************** +* Copyright (c) 2024 Contributors to the Eclipse Foundation +* +* This program and the accompanying materials are made available under the +* terms of the Apache License 2.0 which is available at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* SPDX-License-Identifier: Apache-2.0 +********************************************************************************/ + +use tinyjson::JsonValue; + +use super::{FileStorageType, Storage, StorageConfig, StorageType, StoreItem}; +use std::collections::HashMap; + +use std::io::Write; +use std::sync::mpsc; +use std::sync::mpsc::{Receiver, Sender}; + +use std::fs::File; + +use log; + +pub struct FileStorage { + state: JsonValue, + queue: Sender, +} + +impl Storage for FileStorage { + fn new(config: StorageConfig) -> Self { + match config.storagetype { + StorageType::FileStorageType(FileStorageType { filepath }) => { + log::info!("Initializing file storage on {}", filepath); + let path = filepath.clone(); + println!("Reading storage from {}", path); + let config_str = std::fs::read_to_string(&path).unwrap(); + println!("config_str {}", config_str); + let state: JsonValue = config_str.parse().unwrap(); + let mut state_copy = state.get::>().unwrap().clone(); + let (tx, rx): (Sender, Receiver) = mpsc::channel(); + let fs = FileStorage { state, queue: tx }; + std::thread::spawn(move || loop { + match rx.recv() { + Ok(msg) => { + log::info!("Store value: {} for path {}", msg.value, msg.path); + let mut val: HashMap = HashMap::new(); + val.insert("value".to_string(), JsonValue::String(msg.value.clone())); + state_copy.insert(msg.path.clone(), JsonValue::from(val)); + let out_json: JsonValue = JsonValue::from(state_copy.to_owned()); + let mut file = File::create(&path).unwrap(); + match file.write_all(out_json.format().unwrap().as_bytes()) { + Ok(_) => {} + Err(e) => { + log::error!("Error writing to state storage file: {:?}", e); + break; + } + } + let _ = file.flush(); + drop(file); + } + Err(_) => { + log::error!("Error receiving message"); + break; + } + } + }); + fs + } + _ => { + log::error!("Error: file storage path is invalid"); + std::process::exit(1); + } + } + } + + fn get(&self, vsspath: &str) -> Option<&str> { + log::debug!("Try getting VSS signal {}", vsspath); + if !self + .state + .get::>() + .unwrap() + .contains_key(vsspath) + { + return None; + } + + let entry: Option<&HashMap> = self.state[vsspath].get(); + + if entry.is_some() && entry.unwrap().contains_key("value") { + let value = entry.unwrap()["value"].get::(); + + if let Some(v) = value { + return Some(v); + } + log::warn!( + "Error reading {vsspath}, make sure all values are quoted and stored as string" + ) + } + None + } + + fn set(&self, vsspath: &str, vssvalue: &str) -> Result<(), ()> { + log::debug!("Setting VSS signal {} to {}", vsspath, vssvalue); + self.queue + .send(StoreItem { + path: vsspath.to_string(), + value: vssvalue.to_string(), + }) + .map_err(|_| ()) + } + + fn get_queue(&self) -> Sender { + self.queue.clone() + } +} + +impl FileStorage {} + +#[cfg(test)] +mod tests { + use super::*; + use std::{fs, io::Read}; + use tempfile::{tempfile, Builder}; + + const FILEPATH_PREFIX: &str = "/tmp/test_storage"; + + const TESTJSON: &str = r#"{ + "test_key": { + "value": "test_value" + } + }"#; + + #[test] + fn test_file_storage_new() { + let mut storage_file = Builder::new() + .prefix(FILEPATH_PREFIX) + .suffix(".json") + .tempfile() + .unwrap(); + let filepath = storage_file.path().to_str().unwrap().to_string(); + + writeln!(storage_file, "{}", TESTJSON).unwrap(); + + let config = StorageConfig { + storagetype: StorageType::FileStorageType(FileStorageType { + filepath: filepath.clone(), + }), + }; + + let storage = FileStorage::new(config); + assert!(storage.get("test_key").is_some()); + assert_eq!(storage.get("test_key").unwrap(), "test_value"); + } + + #[test] + fn test_file_storage_get() { + let mut storage_file = Builder::new() + .prefix(FILEPATH_PREFIX) + .suffix(".json") + .tempfile() + .unwrap(); + let filepath = storage_file.path().to_str().unwrap().to_string(); + + writeln!(storage_file, "{}", TESTJSON).unwrap(); + + let config = StorageConfig { + storagetype: StorageType::FileStorageType(FileStorageType { + filepath: filepath.clone(), + }), + }; + + let storage = FileStorage::new(config); + assert_eq!(storage.get("test_key").unwrap(), "test_value"); + assert!(storage.get("non_existent_key").is_none()); + } + + #[test] + fn test_file_storage_set() { + // Create an empty temporary file + let mut storage_file = Builder::new() + .prefix(FILEPATH_PREFIX) + .suffix(".json") + .tempfile() + .unwrap(); + let filepath = storage_file.path().to_str().unwrap().to_string(); + + // let testjson = r#"{}"#; + // writeln!(storage_file, "{}", TESTJSON).unwrap(); + storage_file.write_all(TESTJSON.as_bytes()).unwrap(); + + let config = StorageConfig { + storagetype: StorageType::FileStorageType(FileStorageType { + filepath: filepath.clone(), + }), + }; + + let storage = FileStorage::new(config); + storage.set("test_key", "value-test-set").unwrap(); + + // Allow some time for the background thread to process the set operation + std::thread::sleep(std::time::Duration::from_millis(100)); + + let updated_content = fs::read_to_string(filepath).unwrap(); + print!("updated_content: {}", updated_content); + assert!( + updated_content + == r#"{ + "test_key": { + "value": "value-test-set" + } +}"# + ); + } + + #[test] + fn test_file_storage_invalid_path() { + let config = StorageConfig { + storagetype: StorageType::FileStorageType(FileStorageType { + filepath: "/invalid/path/to/storage.json".to_string(), + }), + }; + + let result = std::panic::catch_unwind(|| { + FileStorage::new(config); + }); + + assert!(result.is_err()); + } +} diff --git a/kuksa-persistence-provider/statestore.json b/kuksa-persistence-provider/statestore.json new file mode 100644 index 0000000..b31e43e --- /dev/null +++ b/kuksa-persistence-provider/statestore.json @@ -0,0 +1,20 @@ +{ + "Vehicle.VehicleIdentification.VIN": { + "value": "DEADBEEF" + }, + "Vehicle.Cabin.HVAC.Station.Row4.Passenger.FanSpeed": { + "value": "41" + }, + "Vehicle.Cabin.Infotainment.Media.Volume": { + "value": "22" + }, + "Vehicle.VehicleIdentification.VehicleInteriorColor": { + "value": "Black" + }, + "Vehicle.Cabin.Infotainment.HMI.TemperatureUnit": { + "value": "C" + }, + "invalid-value": { + "value": "iam-invalid" + } +} \ No newline at end of file From f44ccd76e2a2cb85253f295e356936b912302a03 Mon Sep 17 00:00:00 2001 From: Erik Jaegervall Date: Wed, 6 Nov 2024 14:55:34 +0100 Subject: [PATCH 2/4] Fixing comment --- kuksa-persistence-provider/Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kuksa-persistence-provider/Readme.md b/kuksa-persistence-provider/Readme.md index 4185689..606f5d3 100644 --- a/kuksa-persistence-provider/Readme.md +++ b/kuksa-persistence-provider/Readme.md @@ -4,7 +4,7 @@ All data in KUKSA is ephemeral. However, in a car there is often data that does This provider can achieve this. It can restore certain values upon startup, either sensor (current) values, or actuations. -An example for one-time restoration of current values are attributes that are maybe not set in a default VSS model deployed to ALL cars of a specific variant, but nevertheless are constant of a specific car, such as the VIN or the Vehicle Color. +An example for one-time restoration of current values are attributes that are maybe not set in a default VSS model deployed to ALL cars of a specific variant, but nevertheless are constant of a specific car, such as the VIN or the vehicle color. This provider can also watch (subscribe) certain current or actuation values. This is useful when interacting with components that do not provide their own persistence management. Assume a climate control UI that can react on user input and interact with the HVAC system, but is otherwise stateless. By watching and restoring the desired target temperature, the user's preference is saved and restored, without the HVAC UI needing any specific code to handle this. From 7106596e08f2a023d15431255bfc7610cc7f9bd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Jaegervall=20=28J=C3=A4gervall=29?= <30996601+erikbosch@users.noreply.github.com> Date: Thu, 5 Dec 2024 14:25:31 +0100 Subject: [PATCH 3/4] Apply suggestions from code review Co-authored-by: MathiasDanzeisen <67945942+MathiasDanzeisen@users.noreply.github.com> --- kuksa-persistence-provider/Cargo.toml | 4 +- kuksa-persistence-provider/Readme.md | 58 +++++++++++++++++++++------ 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/kuksa-persistence-provider/Cargo.toml b/kuksa-persistence-provider/Cargo.toml index 9ec9425..cb64a76 100644 --- a/kuksa-persistence-provider/Cargo.toml +++ b/kuksa-persistence-provider/Cargo.toml @@ -18,7 +18,7 @@ prost-types = "0.11.9" tokio = { version="1.40.0", features = ["full"] } # TODO: change this to a a github path once available -djson = { path="../../platform/modules/json-al/djson_rust/" , optional = true } +# djson = { path="../../platform/modules/json-al/djson_rust/" , optional = true } # Uncomment to use djson lib # For testing [dev_dependencies] @@ -27,5 +27,5 @@ tempfile = "3.2.0" [features] default = ["json_tinyjson"] # use a dependable json library, this still requires tiny-json for writing -json_djson = [ "dep:djson","dep:tinyjson" ] +# json_djson = [ "dep:djson","dep:tinyjson" ] # Uncomment to use djson lib json_tinyjson = [ "dep:tinyjson" ] diff --git a/kuksa-persistence-provider/Readme.md b/kuksa-persistence-provider/Readme.md index 606f5d3..197c0c5 100644 --- a/kuksa-persistence-provider/Readme.md +++ b/kuksa-persistence-provider/Readme.md @@ -73,28 +73,60 @@ As the statestore does not make a difference between current and target (actuati ## Features * djson: Use a dependable json library. - Check out the repo with the depenable json library at the same level as the parent folder or project folder of this repo. - Enable with ```cargo build --features json_djson --no-default-features``` + * Check out the repo with the depenable json library at the same level as the parent folder or project folder of this repo. + * Edit `Cargo.toml` and uncomment the following lines + + ```toml + djson = { path="../../platform/modules/json-al/djson_rust/" , optional = true } # Uncommment to use djson + + # ... + + json_djson = [ "dep:djson","dep:tinyjson" ] # Uncommment to use djson + ``` + * Install rust nightly which is needed for djson at the moment [11/2024] + ```bash + rustup toolchain install nightly + rustup default nightly + ``` + * Enable with ```cargo build --features json_djson --no-default-features`````` ## Build ```bash +cargo build +# with features, see above for prerequisites cargo build --features json_djson --no-default-features -``` ## Test -Start kuksa databroker with: +1) Check for empty data point after startup + + * In Terminal A): Start kuksa databroker with: -```bash -docker run -it --rm --net=host ghcr.io/eclipse-kuksa/kuksa-databroker:latest --port 55556 -``` + ```bash + docker run -it --rm --net=host ghcr.io/eclipse-kuksa/kuksa-databroker:latest --port 55556 + ``` -Start kuksa sdk with: + * In Terminal B) Start kuksa sdk with: -```bash -docker run -it --rm --net=host ghcr.io/eclipse-kuksa/kuksa-python-sdk/kuksa-client:latest grpc://127.0.0.1:55556 -# Check Vales in cmd -getValue Vehicle.Cabin.HVAC.Station.Row4.Passenger.FanSpeed -``` + ```bash + docker run -it --rm --net=host ghcr.io/eclipse-kuksa/kuksa-python-sdk/kuksa-client:latest grpc://127.0.0.1:55556 + # Check Vales in cmd + getValue Vehicle.Cabin.HVAC.Station.Row4.Passenger.FanSpeed + ``` + + * In Terminal C) Start kuksa persistency provider with: + + ```bash + cargo run + ``` + +2) Set data point which is stored by persistency provider + * In Terminal B) : + + ```bash + # Set Vales in cmd + setValue Vehicle.Cabin.HVAC.Station.Row4.Passenger.FanSpeed 40 + ``` +3) Restart and check if datapoint with old value is restored by persistency provider From 037815887e218abb6fca8268544b2985ed53e8f5 Mon Sep 17 00:00:00 2001 From: Erik Jaegervall Date: Thu, 5 Dec 2024 14:50:03 +0100 Subject: [PATCH 4/4] Fix pre-commit Also doing cargo update --- kuksa-persistence-provider/Cargo.lock | 173 ++++++++++++-------------- kuksa-persistence-provider/Readme.md | 6 +- 2 files changed, 82 insertions(+), 97 deletions(-) diff --git a/kuksa-persistence-provider/Cargo.lock b/kuksa-persistence-provider/Cargo.lock index 512d268..9c79c27 100644 --- a/kuksa-persistence-provider/Cargo.lock +++ b/kuksa-persistence-provider/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -28,9 +28,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -43,9 +43,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" @@ -77,9 +77,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.91" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "async-stream" @@ -100,7 +100,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -111,7 +111,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -215,15 +215,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" -version = "1.1.31" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "shlex", ] @@ -236,9 +236,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.20" +version = "4.5.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "69371e34337c4c984bbe322360c2547210bf632eb2814bbe78a6e87a2935bd2b" dependencies = [ "clap_builder", "clap_derive", @@ -246,9 +246,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "6e24c1b4099818523236a8ca881d2b45db98dadfb4625cf6608c12069fcbbde1" dependencies = [ "anstream", "anstyle", @@ -265,14 +265,14 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "colorchoice" @@ -280,13 +280,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" -[[package]] -name = "djson" -version = "0.1.0" -dependencies = [ - "tinyjson", -] - [[package]] name = "either" version = "1.13.0" @@ -324,19 +317,19 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "fixedbitset" @@ -418,7 +411,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.6.0", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", @@ -433,9 +426,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -449,12 +442,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "home" version = "0.5.9" @@ -552,12 +539,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.2", ] [[package]] @@ -577,14 +564,14 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "kuksa" version = "0.4.4" -source = "git+https://github.com/eclipse-kuksa/kuksa-databroker.git?branch=feature/refactor_kuksa_crate#f31e2f27a92a4d7cde90342b3a5eb5f6630db71b" +source = "git+https://github.com/eclipse-kuksa/kuksa-databroker.git?branch=feature%2Frefactor_kuksa_crate#f31e2f27a92a4d7cde90342b3a5eb5f6630db71b" dependencies = [ "http", "kuksa-grpc", @@ -598,7 +585,7 @@ dependencies = [ [[package]] name = "kuksa-grpc" version = "0.4.4" -source = "git+https://github.com/eclipse-kuksa/kuksa-databroker.git?branch=feature/refactor_kuksa_crate#f31e2f27a92a4d7cde90342b3a5eb5f6630db71b" +source = "git+https://github.com/eclipse-kuksa/kuksa-databroker.git?branch=feature%2Frefactor_kuksa_crate#f31e2f27a92a4d7cde90342b3a5eb5f6630db71b" dependencies = [ "http", "tokio", @@ -612,7 +599,6 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", - "djson", "env_logger", "kuksa", "log", @@ -626,7 +612,7 @@ dependencies = [ [[package]] name = "kuksa-proto" version = "0.4.1" -source = "git+https://github.com/eclipse-kuksa/kuksa-databroker.git?branch=feature/refactor_kuksa_crate#f31e2f27a92a4d7cde90342b3a5eb5f6630db71b" +source = "git+https://github.com/eclipse-kuksa/kuksa-databroker.git?branch=feature%2Frefactor_kuksa_crate#f31e2f27a92a4d7cde90342b3a5eb5f6630db71b" dependencies = [ "prost", "prost-types", @@ -643,9 +629,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "linux-raw-sys" @@ -698,11 +684,10 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi", "libc", "wasi", "windows-sys 0.52.0", @@ -765,7 +750,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.6.0", + "indexmap 2.7.0", ] [[package]] @@ -785,7 +770,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -821,9 +806,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -953,9 +938,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -991,9 +976,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.38" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags 2.6.0", "errno", @@ -1057,22 +1042,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.213" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.213" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -1107,9 +1092,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1140,9 +1125,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.85" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -1157,9 +1142,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -1170,22 +1155,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.65" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.65" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -1196,9 +1181,9 @@ checksum = "9ab95735ea2c8fd51154d01e39cf13912a78071c2d89abc49a7ef102a7dd725a" [[package]] name = "tokio" -version = "1.41.0" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -1230,7 +1215,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] @@ -1257,9 +1242,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -1346,9 +1331,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -1357,20 +1342,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] @@ -1383,9 +1368,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "untrusted" @@ -1526,5 +1511,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.90", ] diff --git a/kuksa-persistence-provider/Readme.md b/kuksa-persistence-provider/Readme.md index 197c0c5..22074a4 100644 --- a/kuksa-persistence-provider/Readme.md +++ b/kuksa-persistence-provider/Readme.md @@ -79,7 +79,7 @@ As the statestore does not make a difference between current and target (actuati ```toml djson = { path="../../platform/modules/json-al/djson_rust/" , optional = true } # Uncommment to use djson - # ... + # ... json_djson = [ "dep:djson","dep:tinyjson" ] # Uncommment to use djson ``` @@ -94,14 +94,14 @@ As the statestore does not make a difference between current and target (actuati ## Build ```bash -cargo build +cargo build # with features, see above for prerequisites cargo build --features json_djson --no-default-features ## Test 1) Check for empty data point after startup - + * In Terminal A): Start kuksa databroker with: ```bash