From 714556e47565a5b123daa84696a83f4e53b996c0 Mon Sep 17 00:00:00 2001 From: Radu Racariu Date: Fri, 8 May 2026 12:35:36 +0300 Subject: [PATCH] feat: allow empty dict creation via dict! {} Refactor dict macro syntax for consistency and add test for empty dict --- Cargo.lock | 132 ++++++++++++++++++++++------------ Cargo.toml | 2 +- src/haystack/val/dict.rs | 34 +++++---- src/haystack/val/dis_macro.rs | 4 +- tests/zinc/test_dict.rs | 4 +- 5 files changed, 113 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e806e29..1691f66 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,9 +55,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "bstr" @@ -84,9 +84,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.57" +version = "1.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ "find-msvc-tools", "shlex", @@ -150,9 +150,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", ] @@ -293,6 +293,30 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + [[package]] name = "getrandom" version = "0.4.2" @@ -334,9 +358,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "heck" @@ -376,12 +400,12 @@ checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -397,16 +421,18 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.91" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -419,13 +445,13 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.183" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libhaystack" -version = "3.1.5" +version = "3.1.6" dependencies = [ "chrono", "chrono-tz", @@ -523,6 +549,12 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + [[package]] name = "plotters" version = "0.3.7" @@ -596,9 +628,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rayon" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -675,9 +707,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -730,9 +762,15 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "siphasher" -version = "1.0.2" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + +[[package]] +name = "slab" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -783,9 +821,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.22.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "getrandom", "js-sys", @@ -804,11 +842,11 @@ dependencies = [ [[package]] name = "wasip2" -version = "1.0.2+wasi-0.2.9" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", ] [[package]] @@ -817,14 +855,14 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.51.0", ] [[package]] name = "wasm-bindgen" -version = "0.2.114" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" dependencies = [ "cfg-if", "once_cell", @@ -835,9 +873,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.114" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -845,9 +883,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.114" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" dependencies = [ "bumpalo", "proc-macro2", @@ -858,9 +896,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.114" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" dependencies = [ "unicode-ident", ] @@ -901,9 +939,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.91" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" +checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" dependencies = [ "js-sys", "wasm-bindgen", @@ -1017,6 +1055,12 @@ dependencies = [ "wit-bindgen-rust-macro", ] +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + [[package]] name = "wit-bindgen-core" version = "0.51.0" @@ -1098,18 +1142,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.42" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.42" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 0725f5c..5588a2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libhaystack" -version = "3.1.5" +version = "3.1.6" description = "Rust implementation of the Haystack 4 data types, defs, filter, units, and encodings" authors = ["J2 Innovations", "Radu Racariu "] edition = "2024" diff --git a/src/haystack/val/dict.rs b/src/haystack/val/dict.rs index 468103c..34fd2ff 100644 --- a/src/haystack/val/dict.rs +++ b/src/haystack/val/dict.rs @@ -838,7 +838,8 @@ macro_rules! dict_key( /// #[macro_export] macro_rules! dict( - { $($key:tt => $value:expr),* $(,)? } => { + {} => { Dict::new() }; + { $($key:tt => $value:expr),+ $(,)? } => { { let mut map = Dict::new(); $( @@ -966,82 +967,87 @@ mod test { } } + #[test] + fn empty_dict_macro() { + assert!(dict! {}.is_empty()); + } + #[test] fn dict_to_dis_returns_dis() { - let dict = dict!["dis" => Value::make_str("display")]; + let dict = dict! {"dis" => Value::make_str("display")}; assert_eq!(dict_to_dis(&dict, &|_| None, None), "display"); } #[test] fn dict_to_dis_returns_dis_not_str() { - let dict = dict!["dis" => Value::make_ref("display")]; + let dict = dict! {"dis" => Value::make_ref("display")}; assert_eq!(dict_to_dis(&dict, &|_| None, None), "@display"); } #[test] fn dict_to_dis_returns_dis_macro() { - let dict = dict!["foo" => Value::make_str("bar"), "disMacro" => Value::make_str("hello $foo world!")]; + let dict = dict! {"foo" => Value::make_str("bar"), "disMacro" => Value::make_str("hello $foo world!")}; assert_eq!(dict_to_dis(&dict, &|_| None, None), "hello bar world!"); } #[test] fn dict_to_dis_returns_dis_key_translated() { - let dict = dict!["foo" => Value::make_str("bar"), "disKey" => Value::make_str("key")]; + let dict = dict! {"foo" => Value::make_str("bar"), "disKey" => Value::make_str("key")}; assert_eq!(dict_to_dis(&dict, &get_localized, None), "translated"); } #[test] fn dict_to_dis_returns_dis_key_not_translated() { let dict = - dict!["foo" => Value::make_str("bar"), "disKey" => Value::make_str("notTranslated")]; + dict! {"foo" => Value::make_str("bar"), "disKey" => Value::make_str("notTranslated")}; assert_eq!(dict_to_dis(&dict, &get_localized, None), "notTranslated"); } #[test] fn dict_to_dis_returns_name() { - let dict = dict!["name" => Value::make_str("display")]; + let dict = dict! {"name" => Value::make_str("display")}; assert_eq!(dict_to_dis(&dict, &|_| None, None), "display"); } #[test] fn dict_to_dis_returns_def() { - let dict = dict!["def" => Value::make_str("display")]; + let dict = dict! {"def" => Value::make_str("display")}; assert_eq!(dict_to_dis(&dict, &|_| None, None), "display"); } #[test] fn dict_to_dis_returns_tag() { - let dict = dict!["tag" => Value::make_str("display")]; + let dict = dict! {"tag" => Value::make_str("display")}; assert_eq!(dict_to_dis(&dict, &|_| None, None), "display"); } #[test] fn dict_to_dis_returns_nav_name() { - let dict = dict!["navName" => Value::make_str("navName")]; + let dict = dict! {"navName" => Value::make_str("navName")}; assert_eq!(dict_to_dis(&dict, &|_| None, None), "navName"); } #[test] fn dict_to_dis_returns_id() { - let dict = dict!["id" => Value::make_ref("id")]; + let dict = dict! {"id" => Value::make_ref("id")}; assert_eq!(dict_to_dis(&dict, &|_| None, None), "id"); } #[test] fn dict_to_dis_returns_id_dis() { - let dict = dict!["id" => Value::make_ref_with_dis("id", "dis")]; + let dict = dict! {"id" => Value::make_ref_with_dis("id", "dis")}; assert_eq!(dict_to_dis(&dict, &|_| None, None), "dis"); } #[test] fn dict_returns_dis() { - let dict = dict!["dis" => Value::make_str("display")]; + let dict = dict! {"dis" => Value::make_str("display")}; assert_eq!(dict.dis(), "display"); } #[test] fn dict_returns_default_value_if_none_found() { - let dict = dict!["something" => Value::make_str("display")]; + let dict = dict! {"something" => Value::make_str("display")}; assert_eq!( dict_to_dis(&dict, &|_| None, Some("default".into())), "default" diff --git a/src/haystack/val/dis_macro.rs b/src/haystack/val/dis_macro.rs index e21093e..e44ec2a 100644 --- a/src/haystack/val/dis_macro.rs +++ b/src/haystack/val/dis_macro.rs @@ -105,13 +105,13 @@ mod test { fn dict_cb<'a>(name: &str) -> Option> { DICT.get_or_init(|| { - dict![ + dict! { "equipRef" => Value::make_ref("ref"), "siteRef" => Value::make_ref_with_dis("ref2", "refDis"), "string" => Value::make_str("str"), "number" => Value::make_number(2.1), "boolean" => Value::make_bool(true) - ] + } }) .get(name) .map(Cow::Borrowed) diff --git a/tests/zinc/test_dict.rs b/tests/zinc/test_dict.rs index 1f621fe..3ee273b 100644 --- a/tests/zinc/test_dict.rs +++ b/tests/zinc/test_dict.rs @@ -22,7 +22,7 @@ fn test_zinc_dict_encode() { assert_eq!(zinc.unwrap(), r#"{dict:{foo:T},name:"Foo",site}"#); assert_eq!( - dict![ + dict! { "a" => "a", "b" => 100, "c" => true, @@ -40,7 +40,7 @@ fn test_zinc_dict_encode() { "o" => DateTime::from_str("2021-06-19T19:48:23-00:00").expect("DateTime"), "p" => Coord::make(34.0522, 118.2437), "q" => Grid::make_empty() - ] + } .to_zinc_string() .unwrap(), "{a:\"a\",b:100,c:T,d:R,e:[\"str\"],f:{na:NA},g:@ref,h:^symbol,i:`uri`,j:Xstr(\"val\"),k:NA,l,m:20:00:00,n:2021-06-19,o:2021-06-19T19:48:23Z,p:C(34.0522,118.2437),q:<<\nver:\"3.0\"\nempty\n>>}",