From 2f7b71d6076f82feab563abbbdc193f5503b184e Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 15 Jun 2025 16:55:58 +0200 Subject: [PATCH 01/68] Clean up cargo manifest --- Cargo.lock | 451 ++++++++++++++--------------------------------------- Cargo.toml | 55 +++---- 2 files changed, 132 insertions(+), 374 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e2a785d..624cd6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", @@ -34,39 +34,45 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", - "once_cell", + "once_cell_polyfill", "windows-sys", ] +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + [[package]] name = "autocfg" version = "1.4.0" @@ -75,24 +81,15 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bstr" -version = "1.11.3" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" dependencies = [ "memchr", "serde", @@ -100,9 +97,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" [[package]] name = "cast" @@ -112,24 +109,18 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.16" +version = "1.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" dependencies = [ "shlex", ] [[package]] name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "ciborium" @@ -160,9 +151,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.31" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" dependencies = [ "clap_builder", "clap_derive", @@ -170,9 +161,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.31" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" dependencies = [ "anstream", "anstyle", @@ -182,9 +173,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.28" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" dependencies = [ "heck", "proc-macro2", @@ -194,15 +185,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "colored" @@ -213,16 +204,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if 1.0.0", - "wasm-bindgen", -] - [[package]] name = "corn-cli" version = "0.10.0" @@ -236,36 +217,24 @@ dependencies = [ "toml_edit", ] -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - [[package]] name = "criterion" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +checksum = "3bf7af66b0989381bd0be551bd7cc91912a655a58c6918420c9527b1fd8b4679" dependencies = [ "anes", "cast", "ciborium", "clap", "criterion-plot", - "is-terminal", - "itertools 0.10.5", + "itertools 0.13.0", "num-traits", - "once_cell", "oorandom", "plotters", "rayon", "regex", "serde", - "serde_derive", "serde_json", "tinytemplate", "walkdir", @@ -312,31 +281,11 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - [[package]] name = "either" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "equivalent" @@ -354,31 +303,21 @@ dependencies = [ "typeid", ] -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "half" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crunchy", ] [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" [[package]] name = "heck" @@ -386,34 +325,17 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - [[package]] name = "indexmap" -version = "2.7.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown", "serde", ] -[[package]] -name = "is-terminal" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -456,39 +378,31 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.170" +version = "0.2.173" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" +checksum = "d8cfeafaffdbc32176b64fb251369d52ea9f0a8fbc6f8759edffef7b525d64bb" [[package]] name = "libcorn" version = "0.10.0" dependencies = [ - "cfg-if 1.0.0", - "console_error_panic_hook", + "anyhow", "criterion", "indexmap", "mlua", - "paste", - "pest", - "pest_derive", "serde", - "serde-wasm-bindgen", "serde_bytes", "serde_json", "serde_norway", - "thiserror", "toml_edit", - "wasm-bindgen", "wasm-bindgen-test", - "wee_alloc", ] [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -496,21 +410,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "memory_units" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "minicov" @@ -524,9 +432,9 @@ dependencies = [ [[package]] name = "mlua" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3f763c1041eff92ffb5d7169968a327e1ed2ebfe425dac0ee5a35f29082534b" +checksum = "c1f5f8fbebc7db5f671671134b9321c4b9aa9adeafccfd9a8c020ae45c6a35d0" dependencies = [ "bstr", "either", @@ -536,18 +444,19 @@ dependencies = [ "num-traits", "parking_lot", "rustc-hash", + "rustversion", "serde", "serde-value", ] [[package]] name = "mlua-sys" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1901c1a635a22fe9250ffcc4fcc937c16b47c2e9e71adba8784af8bca1f69594" +checksum = "380c1f7e2099cafcf40e51d3a9f20a346977587aa4d012eae1f043149a728a93" dependencies = [ "cc", - "cfg-if 1.0.0", + "cfg-if", "pkg-config", ] @@ -577,15 +486,21 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "oorandom" -version = "11.1.4" +version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "ordered-float" @@ -598,9 +513,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -608,68 +523,17 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", "smallvec", "windows-targets", ] -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pest" -version = "2.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pest_meta" -version = "2.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" -dependencies = [ - "once_cell", - "pest", - "sha2", -] - [[package]] name = "pkg-config" version = "0.3.32" @@ -728,18 +592,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -766,9 +630,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" dependencies = [ "bitflags", ] @@ -810,9 +674,9 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" @@ -837,9 +701,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] @@ -854,31 +718,20 @@ dependencies = [ "serde", ] -[[package]] -name = "serde-wasm-bindgen" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" -dependencies = [ - "js-sys", - "serde", - "wasm-bindgen", -] - [[package]] name = "serde_bytes" -version = "0.11.16" +version = "0.11.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "364fec0df39c49a083c9a8a18a23a6bcfd9af130fe9fe321d18520a0d113e09e" +checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -912,24 +765,13 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest", -] - [[package]] name = "shlex" version = "1.3.0" @@ -938,9 +780,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "strsim" @@ -950,35 +792,15 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.99" +version = "2.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" +checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "thiserror" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tinytemplate" version = "1.2.1" @@ -991,43 +813,38 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", + "toml_write", "winnow", ] [[package]] -name = "typeid" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" - -[[package]] -name = "typenum" -version = "1.18.0" +name = "toml_write" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] -name = "ucd-trie" -version = "0.1.7" +name = "typeid" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "unicode-ident" @@ -1047,12 +864,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - [[package]] name = "walkdir" version = "2.5.0" @@ -1069,7 +880,7 @@ version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", @@ -1095,7 +906,7 @@ version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "once_cell", "wasm-bindgen", @@ -1168,34 +979,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "wee_alloc" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "memory_units", - "winapi", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" version = "0.1.9" @@ -1205,12 +988,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-sys" version = "0.59.0" @@ -1286,9 +1063,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.3" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 2725ac9..83f1025 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,22 +9,19 @@ license = "MIT" description = "Parsing engine for Corn, a simple and pain-free configuration language." repository = "https://github.com/JakeStanger/corn" categories = ["config", "parsing"] -keywords = ["configuration", "language", "wasm", "pest", "peg"] -authors = ["Jake Stanger "] +keywords = ["configuration", "language", "wasm", "peg"] +authors = [ + "Jake Stanger ", + "Matilde Morrone ", +] homepage = "https://cornlang.dev/" documentation = "https://docs.rs/libcorn" readme = "README.md" [features] # WASM support -wasm = [ - "dep:wasm-bindgen", - "dep:serde-wasm-bindgen", - "dep:console_error_panic_hook", - "dep:wee_alloc", -] - -# Lua version support +wasm = [] +# Lua support lua51 = ["dep:mlua", "mlua/lua51"] lua52 = ["dep:mlua", "mlua/lua52"] lua53 = ["dep:mlua", "mlua/lua53"] @@ -32,49 +29,34 @@ lua54 = ["dep:mlua", "mlua/lua54"] luajit = ["dep:mlua", "mlua/luajit"] luajit52 = ["dep:mlua", "mlua/luajit52"] -# Internal features -bench = ["dep:criterion"] - [lib] name = "corn" crate-type = ["cdylib", "rlib"] [dependencies] # Core -pest = "2.7.15" -pest_derive = "2.7.15" -serde = { version = "1.0.218", features = ["derive"] } -indexmap = { version = "2.7.1", features = ["serde"] } - -# Error handling -thiserror = "2.0.12" - -# Utilities -cfg-if = "1.0.0" - -# WASM support (optional) -wasm-bindgen = { version = "0.2.100", optional = true } -serde-wasm-bindgen = { version = "0.6.5", optional = true } -console_error_panic_hook = { version = "0.1.7", optional = true } -wee_alloc = { version = "0.4.5", optional = true } +serde = "1.0.219" +indexmap = { version = "2.9.0", features = ["serde"] } +# # WASM support (optional) +# wasm-bindgen = { version = "0.2.100", optional = true } +# serde-wasm-bindgen = { version = "0.6.5", optional = true } +# console_error_panic_hook = { version = "0.1.7", optional = true } # Lua support (optional) -mlua = { version = "0.10.3", features = [ +mlua = { version = "0.10.5", features = [ "module", "macros", "serialize", ], optional = true } -# Benchmarking (optional) -criterion = { version = "0.5.1", features = ["html_reports"], optional = true } - [dev-dependencies] -paste = "1.0.15" wasm-bindgen-test = { version = "0.3.50" } serde_json = "1.0.140" serde_norway = "0.9.42" -serde_bytes = "0.11.16" -toml_edit = { version = "0.22.24", features = ["serde"] } +serde_bytes = "0.11.17" +toml_edit = { version = "0.22.27", features = ["serde"] } +anyhow = "1.0.97" +criterion = { version = "0.6.0", features = ["html_reports"] } [profile.release] lto = true @@ -84,4 +66,3 @@ strip = true [[bench]] name = "serde" harness = false -required-features = ["bench"] From d2b29f6949e6afc9bbbe876b377c67f09fa59c29 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 15 Jun 2025 16:59:05 +0200 Subject: [PATCH 02/68] Add implementation for Value --- Cargo.lock | 1 + Cargo.toml | 1 + src/lib.rs | 134 +++++++++++----------- src/value/de.rs | 114 +++++++++++++++++++ src/value/integer.rs | 89 +++++++++++++++ src/value/mod.rs | 261 +++++++++++++++++++++++++++++++++++++++++++ src/value/ser.rs | 30 +++++ 7 files changed, 565 insertions(+), 65 deletions(-) create mode 100644 src/value/de.rs create mode 100644 src/value/integer.rs create mode 100644 src/value/mod.rs create mode 100644 src/value/ser.rs diff --git a/Cargo.lock b/Cargo.lock index 624cd6b..8112b76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -389,6 +389,7 @@ dependencies = [ "anyhow", "criterion", "indexmap", + "itoa", "mlua", "serde", "serde_bytes", diff --git a/Cargo.toml b/Cargo.toml index 83f1025..3200e0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ mlua = { version = "0.10.5", features = [ "macros", "serialize", ], optional = true } +itoa = "1.0.15" [dev-dependencies] wasm-bindgen-test = { version = "0.3.50" } diff --git a/src/lib.rs b/src/lib.rs index f06dfb9..b878ea7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,72 +1,76 @@ -use indexmap::IndexMap; -use serde::Serialize; -use std::borrow::Cow; -use std::collections::HashMap; -use std::fmt::{Display, Formatter}; +// use indexmap::IndexMap; +// use serde::Serialize; +// use std::borrow::Cow; +// use std::collections::HashMap; +// use std::fmt::{Display, Formatter}; -pub use crate::de::{from_slice, from_str}; -pub use crate::parser::{parse, Rule}; +// pub use crate::de::{from_slice, from_str}; +// pub use crate::parser::{parse, Rule}; -pub mod error; -mod parser; +// pub mod error; +// mod parser; -mod de; -#[cfg(any( - feature = "lua51", - feature = "lua52", - feature = "lua53", - feature = "lua54", - feature = "luajit", - feature = "luajit52" -))] -mod lua; -#[cfg(feature = "wasm")] -mod wasm; +// mod de; +// #[cfg(any( +// feature = "lua51", +// feature = "lua52", +// feature = "lua53", +// feature = "lua54", +// feature = "luajit", +// feature = "luajit52" +// ))] +// mod lua; +// #[cfg(feature = "wasm")] +// mod wasm; -/// A map of input names and values. -/// The names include their `$` prefix. -pub type Inputs<'a> = HashMap<&'a str, Value<'a>>; +// /// A map of input names and values. +// /// The names include their `$` prefix. +// pub type Inputs<'a> = HashMap<&'a str, Value<'a>>; -/// A map of keys to their values. -pub type Object<'a> = IndexMap, Value<'a>>; +// /// A map of keys to their values. +// pub type Object<'a> = IndexMap, Value<'a>>; -#[derive(Serialize, Debug, Clone)] -#[serde(untagged)] -pub enum Value<'a> { - /// Key/value map. Values can be mixed types. - Object(Object<'a>), - /// Array of values, can be mixed types. - Array(Vec>), - /// UTF-8 string - String(Cow<'a, str>), - /// 64-bit signed integer. - Integer(i64), - /// 64-bit (double precision) floating point number. - Float(f64), - /// true or false - Boolean(bool), - /// `null` literal. - /// - /// Takes an optional unit type as the `toml` crate - /// errors when encountering unit types, - /// but can handle `None` types. - Null(Option<()>), -} +// #[derive(Serialize, Debug, Clone)] +// #[serde(untagged)] +// pub enum Value<'a> { +// /// Key/value map. Values can be mixed types. +// Object(Object<'a>), +// /// Array of values, can be mixed types. +// Array(Vec>), +// /// UTF-8 string +// String(Cow<'a, str>), +// /// 64-bit signed integer. +// Integer(i64), +// /// 64-bit (double precision) floating point number. +// Float(f64), +// /// true or false +// Boolean(bool), +// /// `null` literal. +// /// +// /// Takes an optional unit type as the `toml` crate +// /// errors when encountering unit types, +// /// but can handle `None` types. +// Null(Option<()>), +// } -impl Display for Value<'_> { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}", - match self { - Value::Object(_) => "object", - Value::Array(_) => "array", - Value::String(_) => "string", - Value::Integer(_) => "integer", - Value::Float(_) => "float", - Value::Boolean(_) => "boolean", - Value::Null(_) => "null", - } - ) - } -} +// impl Display for Value<'_> { +// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { +// write!( +// f, +// "{}", +// match self { +// Value::Object(_) => "object", +// Value::Array(_) => "array", +// Value::String(_) => "string", +// Value::Integer(_) => "integer", +// Value::Float(_) => "float", +// Value::Boolean(_) => "boolean", +// Value::Null(_) => "null", +// } +// ) +// } +// } + +mod value; + +pub use value::Value; \ No newline at end of file diff --git a/src/value/de.rs b/src/value/de.rs new file mode 100644 index 0000000..5b80b29 --- /dev/null +++ b/src/value/de.rs @@ -0,0 +1,114 @@ +use serde::{de::Visitor, Deserialize}; + +use crate::{Object, Value}; + +impl<'de> Deserialize<'de> for Value { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct ValueVisitor; + + impl<'de> Visitor<'de> for ValueVisitor { + type Value = Value; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("any valid Corn value") + } + + #[inline] + fn visit_bool(self, v: bool) -> Result + where + E: serde::de::Error, + { + Ok(Value::Boolean(v)) + } + + #[inline] + fn visit_i64(self, v: i64) -> Result + where + E: serde::de::Error, + { + Ok(Value::Integer(v.into())) + } + + #[inline] + fn visit_u64(self, v: u64) -> Result + where + E: serde::de::Error, + { + Ok(Value::Integer(v.into())) + } + + fn visit_f64(self, v: f64) -> Result + where + E: serde::de::Error, + { + Ok(Value::Float(v)) + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + self.visit_string(String::from(v)) + } + + fn visit_string(self, v: String) -> Result + where + E: serde::de::Error, + { + Ok(Value::String(v)) + } + + fn visit_none(self) -> Result + where + E: serde::de::Error, + { + Ok(Value::Null) + } + + fn visit_some(self, deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + Deserialize::deserialize(deserializer) + } + + fn visit_unit(self) -> Result + where + E: serde::de::Error, + { + Ok(Value::Null) + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + let mut vec = Vec::new(); + + while let Some(elem) = seq.next_element()? { + vec.push(elem); + } + + Ok(Value::Array(vec)) + } + + fn visit_map(self, mut map: A) -> Result + where + A: serde::de::MapAccess<'de>, + { + let mut dict = Object::new(); + + while let Some((key, value)) = map.next_entry()? { + dict.insert(key, value); + } + + Ok(Value::Object(dict)) + } + } + + deserializer.deserialize_any(ValueVisitor) + } +} diff --git a/src/value/integer.rs b/src/value/integer.rs new file mode 100644 index 0000000..5d2063e --- /dev/null +++ b/src/value/integer.rs @@ -0,0 +1,89 @@ +use serde::Serialize; +use std::fmt::{Debug, Display}; + +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)] +pub struct Integer { + inner: IntegerType, +} + +impl Debug for Integer { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Integer({})", self) + } +} + +impl Display for Integer { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.inner { + IntegerType::Negative(n) => f.write_str(itoa::Buffer::new().format(n)), + IntegerType::Positive(n) => f.write_str(itoa::Buffer::new().format(n)), + } + } +} + +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)] +enum IntegerType { + Negative(i64), + Positive(u64), +} + +impl From for Integer { + fn from(value: i64) -> Self { + Self { + inner: IntegerType::Negative(value), + } + } +} + +impl From for Integer { + fn from(value: u64) -> Self { + Self { + inner: IntegerType::Positive(value), + } + } +} + +impl Integer { + pub const fn is_i64(&self) -> bool { + match self.inner { + IntegerType::Positive(n) => n <= i64::MAX as u64, + IntegerType::Negative(_) => true, + } + } + + pub const fn is_u64(&self) -> bool { + matches!(self.inner, IntegerType::Positive(_)) + } + + pub const fn as_i64(&self) -> Option { + match self.inner { + IntegerType::Negative(n) => Some(n), + IntegerType::Positive(n) => { + if n <= i64::MAX as u64 { + Some(n as i64) + } else { + None + } + } + } + } + + pub const fn as_u64(&self) -> Option { + match self.inner { + IntegerType::Positive(n) => Some(n), + IntegerType::Negative(_) => None, + } + } +} + +impl Serialize for Integer { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match self.inner { + IntegerType::Negative(integer) => serializer.serialize_i64(integer), + IntegerType::Positive(integer) => serializer.serialize_u64(integer), + } + } +} diff --git a/src/value/mod.rs b/src/value/mod.rs new file mode 100644 index 0000000..27e9448 --- /dev/null +++ b/src/value/mod.rs @@ -0,0 +1,261 @@ +use indexmap::IndexMap; + +mod de; +mod integer; +mod ser; + +pub use integer::Integer; + +/// Object: Key-value collection that preserves insertion order +pub type Object = IndexMap; + +/// Represents a Corn configuration value. +/// +/// This enum encompasses all possible value types in the Corn language specification: +/// - String: UTF-8 string values +/// - Integer: 64-bit signed integers +/// - Float: 64-bit floating point numbers +/// - Boolean: true/false values +/// - Object: Key-value collection that preserves insertion order +/// - Array: Ordered collections of values +/// - Null: Represents absence of a value +#[derive(Debug, Clone)] +pub enum Value { + /// A UTF-8 string value + String(String), + /// A 64-bit signed integer + Integer(Integer), + /// A 64-bit floating point number + Float(f64), + /// A boolean value (true or false) + Boolean(bool), + /// A key-value collection that preserves insertion order + Object(Object), + /// An ordered collection of values + Array(Vec), + /// Represents the absence of a value + Null, +} + +impl Value { + /// Returns true if the value is a String. + pub const fn is_string(&self) -> bool { + matches!(self, Self::String(_)) + } + + /// Returns true if the value is an Integer. + pub const fn is_integer(&self) -> bool { + matches!(self, Self::Integer(_)) + } + + /// Returns true if the value is a Float. + pub const fn is_float(&self) -> bool { + matches!(self, Self::Float(_)) + } + + /// Returns true if the value is a Boolean. + pub const fn is_boolean(&self) -> bool { + matches!(self, Self::Boolean(_)) + } + + /// Returns true if the value is an Object. + pub const fn is_object(&self) -> bool { + matches!(self, Self::Object(_)) + } + + /// Returns true if the value is an Array. + pub const fn is_array(&self) -> bool { + matches!(self, Self::Array(_)) + } + + /// Returns true if the value is Null. + pub const fn is_null(&self) -> bool { + matches!(self, Self::Null) + } + + /// Returns the inner String if this value is a String, otherwise None. + pub fn as_string(&self) -> Option<&String> { + match self { + Self::String(s) => Some(s), + _ => None, + } + } + + /// Returns the inner Integer if this value is an Integer, otherwise None. + pub const fn as_integer(&self) -> Option<&Integer> { + match self { + Self::Integer(integer) => Some(integer), + _ => None, + } + } + + /// Returns the inner Float if this value is a Float, otherwise None. + pub const fn as_float(&self) -> Option<&f64> { + match self { + Self::Float(f) => Some(f), + _ => None, + } + } + + /// Returns the inner Boolean if this value is a Boolean, otherwise None. + pub const fn as_boolean(&self) -> Option<&bool> { + match self { + Self::Boolean(b) => Some(b), + _ => None, + } + } + + /// Returns the inner Object if this value is an Object, otherwise None. + pub fn as_object(&self) -> Option<&Object> { + match self { + Self::Object(obj) => Some(obj), + _ => None, + } + } + + /// Returns the inner Array if this value is an Array, otherwise None. + pub fn as_array(&self) -> Option<&Vec> { + match self { + Self::Array(arr) => Some(arr), + _ => None, + } + } + + /// Returns a mutable reference to the inner String if this value is a String, otherwise None. + pub fn as_string_mut(&mut self) -> Option<&mut String> { + match self { + Self::String(s) => Some(s), + _ => None, + } + } + + /// Returns a mutable reference to the inner Integer if this value is an Integer, otherwise None. + pub fn as_integer_mut(&mut self) -> Option<&mut Integer> { + match self { + Self::Integer(i) => Some(i), + _ => None, + } + } + + /// Returns a mutable reference to the inner Float if this value is a Float, otherwise None. + pub fn as_float_mut(&mut self) -> Option<&mut f64> { + match self { + Self::Float(f) => Some(f), + _ => None, + } + } + + /// Returns a mutable reference to the inner Boolean if this value is a Boolean, otherwise None. + pub fn as_boolean_mut(&mut self) -> Option<&mut bool> { + match self { + Self::Boolean(b) => Some(b), + _ => None, + } + } + + /// Returns a mutable reference to the inner Object if this value is an Object, otherwise None. + pub fn as_object_mut(&mut self) -> Option<&mut Object> { + match self { + Self::Object(obj) => Some(obj), + _ => None, + } + } + + /// Returns a mutable reference to the inner Array if this value is an Array, otherwise None. + pub fn as_array_mut(&mut self) -> Option<&mut Vec> { + match self { + Self::Array(arr) => Some(arr), + _ => None, + } + } + + /// Takes the inner String if this value is a String, otherwise None. + pub fn take_string(self) -> Option { + match self { + Self::String(s) => Some(s), + _ => None, + } + } + + /// Takes the inner Integer if this value is an Integer, otherwise None. + pub fn take_integer(self) -> Option { + match self { + Self::Integer(i) => Some(i), + _ => None, + } + } + + /// Takes the inner Float if this value is a Float, otherwise None. + pub fn take_float(self) -> Option { + match self { + Self::Float(f) => Some(f), + _ => None, + } + } + + /// Takes the inner Boolean if this value is a Boolean, otherwise None. + pub fn take_boolean(self) -> Option { + match self { + Self::Boolean(b) => Some(b), + _ => None, + } + } + + /// Takes the inner Object if this value is an Object, otherwise None. + pub fn take_object(self) -> Option { + match self { + Self::Object(obj) => Some(obj), + _ => None, + } + } + + /// Takes the inner Array if this value is an Array, otherwise None. + pub fn take_array(self) -> Option> { + match self { + Self::Array(arr) => Some(arr), + _ => None, + } + } + + /// Returns true if the value is empty. + /// An empty value is an empty String, empty Object, empty Array, or Null. + pub fn is_empty(&self) -> bool { + match self { + Self::String(s) => s.is_empty(), + Self::Object(obj) => obj.is_empty(), + Self::Array(arr) => arr.is_empty(), + Self::Null => true, + _ => false, + } + } + + /// Returns the number of elements in this Value. + /// For objects this is the number of key-value pairs, for arrays it's the number of elements, + /// for strings it's the string length, and for other types it's 0. + pub fn len(&self) -> usize { + match self { + Self::String(s) => s.len(), + Self::Object(obj) => obj.len(), + Self::Array(arr) => arr.len(), + _ => 0, + } + } + + /// Get a reference to a value in an object by key. + /// Returns None if the value is not an object or if the key doesn't exist. + pub fn get(&self, key: &str) -> Option<&Value> { + match self { + Self::Object(obj) => obj.get(key), + _ => None, + } + } + + /// Get a reference to a value in an array by index. + /// Returns None if the value is not an array or if the index is out of bounds. + pub fn get_index(&self, index: usize) -> Option<&Value> { + match self { + Self::Array(arr) => arr.get(index), + _ => None, + } + } +} diff --git a/src/value/ser.rs b/src/value/ser.rs new file mode 100644 index 0000000..65abb5b --- /dev/null +++ b/src/value/ser.rs @@ -0,0 +1,30 @@ +use serde::Serialize; + +use crate::Value; + +impl Serialize for Value { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match self { + Self::String(s) => serializer.serialize_str(s), + Self::Integer(i) => i.serialize(serializer), + Self::Float(f) => f.serialize(serializer), + Self::Boolean(v) => serializer.serialize_bool(*v), + Self::Object(obj) => { + use serde::ser::SerializeMap; + let mut map = serializer.serialize_map(Some(obj.len()))?; + + for (k, v) in obj { + map.serialize_entry(k, v)?; + } + + map.end() + } + Self::Array(v) => v.serialize(serializer), + Self::Null => serializer.serialize_unit(), + } + } +} From 008abd7fa315ebb7fceda1c86b30e5ba0453753c Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 15 Jun 2025 17:02:49 +0200 Subject: [PATCH 03/68] Make object and integer public --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index b878ea7..ab9dde5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,4 +73,4 @@ mod value; -pub use value::Value; \ No newline at end of file +pub use value::{Object, Value, Integer}; \ No newline at end of file From 27daca2cba93817e5dfeaa967b4b7f935a3a6a13 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 15 Jun 2025 17:54:46 +0200 Subject: [PATCH 04/68] Fix too compact tests --- assets/inputs/compact.corn | 2 +- assets/inputs/very_compact.corn | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/inputs/compact.corn b/assets/inputs/compact.corn index 49185de..0e78286 100644 --- a/assets/inputs/compact.corn +++ b/assets/inputs/compact.corn @@ -8,7 +8,7 @@ seven={foo=[] bar=[]} eight=["foo""bar"] - nine=[truefalse] + nine=[true false] ten=[1 2] eleven=[[][]] twelve=[{}{}] diff --git a/assets/inputs/very_compact.corn b/assets/inputs/very_compact.corn index 3932084..4af65a8 100644 --- a/assets/inputs/very_compact.corn +++ b/assets/inputs/very_compact.corn @@ -1 +1 @@ -{one={foo="bar" bar="foo"} two={foo=1 bar=2} three={foo=1.0 bar=2.0} four={foo=true bar=false} five={foo=null bar=null} six={foo={} bar={}} seven={foo=[] bar=[]} eight=["foo""bar"] nine=[truefalse] ten=[1 2] eleven=[[][]] twelve=[{}{}]} +{one={foo="bar" bar="foo"} two={foo=1 bar=2} three={foo=1.0 bar=2.0} four={foo=true bar=false} five={foo=null bar=null} six={foo={} bar={}} seven={foo=[] bar=[]} eight=["foo""bar"] nine=[true false] ten=[1 2] eleven=[[][]] twelve=[{}{}]} From d1269c8575840f8e435d8f180d05f77b00ff804a Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 15 Jun 2025 17:55:21 +0200 Subject: [PATCH 05/68] Implement a full lexer --- Cargo.lock | 96 +++++++++++++++++++++++++++++++++++++++ Cargo.toml | 4 ++ src/lexer.rs | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 src/lexer.rs diff --git a/Cargo.lock b/Cargo.lock index 8112b76..a6bfcae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,6 +79,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + [[package]] name = "bitflags" version = "2.9.1" @@ -303,6 +309,12 @@ dependencies = [ "typeid", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "half" version = "2.6.0" @@ -376,6 +388,12 @@ dependencies = [ "wasm-bindgen", ] +[[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.173" @@ -390,11 +408,14 @@ dependencies = [ "criterion", "indexmap", "itoa", + "logos", "mlua", + "paste", "serde", "serde_bytes", "serde_json", "serde_norway", + "thiserror", "toml_edit", "wasm-bindgen-test", ] @@ -415,6 +436,40 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +[[package]] +name = "logos" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab6f536c1af4c7cc81edf73da1f8029896e7e1e16a219ef09b184e76a296f3db" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-codegen" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "189bbfd0b61330abea797e5e9276408f2edbe4f822d7ad08685d67419aafb34e" +dependencies = [ + "beef", + "fnv", + "lazy_static", + "proc-macro2", + "quote", + "regex-syntax", + "rustc_version", + "syn", +] + +[[package]] +name = "logos-derive" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebfe8e1a19049ddbfccbd14ac834b215e11b85b90bab0c2dba7c7b92fb5d5cba" +dependencies = [ + "logos-codegen", +] + [[package]] name = "memchr" version = "2.7.5" @@ -535,6 +590,12 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pkg-config" version = "0.3.32" @@ -673,6 +734,15 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustversion" version = "1.0.21" @@ -700,6 +770,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + [[package]] name = "serde" version = "1.0.219" @@ -802,6 +878,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tinytemplate" version = "1.2.1" diff --git a/Cargo.toml b/Cargo.toml index 3200e0c..80cf21d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ crate-type = ["cdylib", "rlib"] # Core serde = "1.0.219" indexmap = { version = "2.9.0", features = ["serde"] } + # # WASM support (optional) # wasm-bindgen = { version = "0.2.100", optional = true } # serde-wasm-bindgen = { version = "0.6.5", optional = true } @@ -49,6 +50,8 @@ mlua = { version = "0.10.5", features = [ "serialize", ], optional = true } itoa = "1.0.15" +logos = "0.15.0" +thiserror = "2.0.12" [dev-dependencies] wasm-bindgen-test = { version = "0.3.50" } @@ -58,6 +61,7 @@ serde_bytes = "0.11.17" toml_edit = { version = "0.22.27", features = ["serde"] } anyhow = "1.0.97" criterion = { version = "0.6.0", features = ["html_reports"] } +paste = "1.0.15" [profile.release] lto = true diff --git a/src/lexer.rs b/src/lexer.rs new file mode 100644 index 0000000..8ca084b --- /dev/null +++ b/src/lexer.rs @@ -0,0 +1,124 @@ +use std::{ + fmt, + num::{ParseFloatError, ParseIntError}, +}; +use thiserror::Error; + +use logos::{Logos, SpannedIter}; + +pub type Spanned = Result<(Loc, Tok, Loc), Error>; + +pub struct Lexer<'input> { + // instead of an iterator over characters, we have a token iterator + token_stream: SpannedIter<'input, Token>, +} + +impl<'input> Lexer<'input> { + pub fn new(input: &'input str) -> Self { + // the Token::lexer() method is provided by the Logos trait + Self { + token_stream: Token::lexer(input).spanned(), + } + } +} + +impl<'input> Iterator for Lexer<'input> { + type Item = Spanned; + + fn next(&mut self) -> Option { + self.token_stream + .next() + .map(|(token, span)| Ok((span.start, token?, span.end))) + } +} + +#[derive(Debug, Default, Error, Clone, PartialEq, Eq)] +pub enum LexicalError { + #[error("Integer parsing error: {0}")] + InvalidInteger(#[from] ParseIntError), + #[error("Float parsing error: {0}")] + InvalidFloat(#[from] ParseFloatError), + #[default] + #[error("Encountered invalid token")] + InvalidToken, +} + +#[derive(Logos, Debug, Clone, PartialEq)] +#[logos(error = LexicalError)] +#[logos(skip r"[\s\t\r\n\f]+")] // Whitespace +#[logos(skip r"//[^\n\r]*[\n\r]*")] // Inline comments +#[logos(skip r"/\*([^*/]|\*[^/]|/[^*])*\*/")] // Multiline comments +pub enum Token { + #[token("let")] + Let, + + #[token("in")] + In, + + #[token("null")] + Null, + + #[token("=")] + Equals, + + #[token("{")] + OpenBrace, + + #[token("}")] + CloseBrace, + + #[token("[")] + OpenBracket, + + #[token("]")] + CloseBracket, + + #[token(".")] + Chain, + + #[token("..")] + Spread, + + #[regex(r#""[^"]*""#, |lex| lex.slice().trim_matches('"').to_string())] + StringLiteral(String), + + // FIXME: better parsing of integers + #[regex(r"-?[0-9]+(_[0-9]+)*", |lex| lex.slice().replace("_", "").parse::())] + Integer(i64), + + #[regex(r"-?[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?", |lex| lex.slice().parse::())] + Float(f64), + + #[token("false", |_| false)] + #[token("true", |_| true)] + Boolean(bool), + + #[regex(r"\$[a-zA-Z_][a-zA-Z0-9_]*", |lex| lex.slice().to_string())] + InputName(String), + + #[regex(r"'[^']*'|[^\s.=0-9\[\]{}-][^\s.=]*", |lex| lex.slice().trim_matches('\'').to_string())] + Key(String), +} + +impl fmt::Display for Token { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Let => write!(f, "let"), + Self::In => write!(f, "in"), + Self::Null => write!(f, "null"), + Self::Equals => write!(f, "="), + Self::OpenBrace => write!(f, "{{"), + Self::CloseBrace => write!(f, "}}"), + Self::OpenBracket => write!(f, "["), + Self::CloseBracket => write!(f, "]"), + Self::Chain => write!(f, "."), + Self::Spread => write!(f, ".."), + Self::StringLiteral(lit) => lit.fmt(f), + Self::Integer(int) => int.fmt(f), + Self::Float(float) => float.fmt(f), + Self::Boolean(bool) => bool.fmt(f), + Self::InputName(name) => name.fmt(f), + Self::Key(key) => key.fmt(f), + } + } +} From 56abcf6dc1d8094d0878f269312f44ed1c49117a Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 15 Jun 2025 18:09:11 +0200 Subject: [PATCH 06/68] Add more exaustive integer parsing --- src/lexer.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lexer.rs b/src/lexer.rs index 8ca084b..36962d5 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -6,6 +6,8 @@ use thiserror::Error; use logos::{Logos, SpannedIter}; +use crate::Integer; + pub type Spanned = Result<(Loc, Tok, Loc), Error>; pub struct Lexer<'input> { @@ -82,9 +84,9 @@ pub enum Token { #[regex(r#""[^"]*""#, |lex| lex.slice().trim_matches('"').to_string())] StringLiteral(String), - // FIXME: better parsing of integers - #[regex(r"-?[0-9]+(_[0-9]+)*", |lex| lex.slice().replace("_", "").parse::())] - Integer(i64), + #[regex(r"-[0-9]+(_[0-9]+)*", |lex| lex.slice().replace("_", "").parse::().map(Integer::from))] + #[regex(r"[0-9]+(_[0-9]+)*", |lex| lex.slice().replace("_", "").parse::().map(Integer::from))] + Integer(Integer), #[regex(r"-?[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?", |lex| lex.slice().parse::())] Float(f64), From 6420c79c7de4dec530a179e0771de7a7ce38d9a6 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Mon, 16 Jun 2025 20:00:01 +0200 Subject: [PATCH 07/68] Implement a lalrpop parser --- Cargo.lock | 241 ++++++++++++++ Cargo.toml | 10 +- assets/inputs/complex_keys.corn | 2 +- build.rs | 5 + src/ast.rs | 69 ++++ src/corn.lalrpop | 87 +++++ src/de.rs | 543 -------------------------------- src/lexer.rs | 34 +- src/lib.rs | 68 ++-- 9 files changed, 459 insertions(+), 600 deletions(-) create mode 100644 build.rs create mode 100644 src/ast.rs create mode 100644 src/corn.lalrpop delete mode 100644 src/de.rs diff --git a/Cargo.lock b/Cargo.lock index a6bfcae..dddd47b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -73,6 +73,15 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +[[package]] +name = "ascii-canvas" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1e3e699d84ab1b0911a1010c5c106aa34ae89aeac103be5ce0c3859db1e891" +dependencies = [ + "term", +] + [[package]] name = "autocfg" version = "1.4.0" @@ -85,12 +94,36 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitflags" version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bstr" version = "1.12.0" @@ -223,6 +256,15 @@ dependencies = [ "toml_edit", ] +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + [[package]] name = "criterion" version = "0.6.0" @@ -287,12 +329,41 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "ena" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +dependencies = [ + "log", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -309,12 +380,28 @@ dependencies = [ "typeid", ] +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "half" version = "2.6.0" @@ -337,6 +424,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys", +] + [[package]] name = "indexmap" version = "2.9.0" @@ -372,6 +468,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.15" @@ -388,6 +493,47 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lalrpop" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4ebbd48ce411c1d10fb35185f5a51a7bfa3d8b24b4e330d30c9e3a34129501" +dependencies = [ + "ascii-canvas", + "bit-set", + "ena", + "itertools 0.14.0", + "lalrpop-util", + "petgraph", + "pico-args", + "regex", + "regex-syntax", + "sha3", + "string_cache", + "term", + "unicode-xid", + "walkdir", +] + +[[package]] +name = "lalrpop-util" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5baa5e9ff84f1aefd264e6869907646538a52147a755d494517a8007fb48733" +dependencies = [ + "regex-automata", + "rustversion", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -408,6 +554,8 @@ dependencies = [ "criterion", "indexmap", "itoa", + "lalrpop", + "lalrpop-util", "logos", "mlua", "paste", @@ -531,6 +679,12 @@ dependencies = [ "syn", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "num-traits" version = "0.2.19" @@ -596,6 +750,31 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pkg-config" version = "0.3.32" @@ -630,6 +809,12 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "proc-macro-error-attr2" version = "2.0.0" @@ -849,18 +1034,46 @@ dependencies = [ "serde", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "string_cache" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared", + "precomputed-hash", +] + [[package]] name = "strsim" version = "0.11.1" @@ -878,6 +1091,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "term" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a984c8d058c627faaf5e8e2ed493fa3c51771889196de1016cf9c1c6e90d750" +dependencies = [ + "home", + "windows-sys", +] + [[package]] name = "thiserror" version = "2.0.12" @@ -943,12 +1166,24 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "unsafe-libyaml-norway" version = "0.2.15" @@ -961,6 +1196,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "walkdir" version = "2.5.0" diff --git a/Cargo.toml b/Cargo.toml index 80cf21d..69f9191 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,10 @@ crate-type = ["cdylib", "rlib"] # Core serde = "1.0.219" indexmap = { version = "2.9.0", features = ["serde"] } +logos = "0.15.0" +lalrpop-util = { version = "0.22.2", features = ["lexer"] } +itoa = "1.0.15" +thiserror = "2.0.12" # # WASM support (optional) # wasm-bindgen = { version = "0.2.100", optional = true } @@ -49,9 +53,9 @@ mlua = { version = "0.10.5", features = [ "macros", "serialize", ], optional = true } -itoa = "1.0.15" -logos = "0.15.0" -thiserror = "2.0.12" + +[build-dependencies] +lalrpop = "0.22.2" [dev-dependencies] wasm-bindgen-test = { version = "0.3.50" } diff --git a/assets/inputs/complex_keys.corn b/assets/inputs/complex_keys.corn index cb74912..fca06cc 100644 --- a/assets/inputs/complex_keys.corn +++ b/assets/inputs/complex_keys.corn @@ -2,7 +2,7 @@ with_underscore = 0 with-dash = 1 with_🌽 = 2 - !"£$%^&*()_ = 3 + !£$%^&*()_ = 3 j12345 = 4 foo.bar-baz = "hello" apple-pie.crust = "yum" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..ab1424e --- /dev/null +++ b/build.rs @@ -0,0 +1,5 @@ +fn main() { + println!("cargo::rerun-if-changed=src/corn.lalrpop"); + + lalrpop::process_src().expect("Failed to parse grammar"); +} diff --git a/src/ast.rs b/src/ast.rs new file mode 100644 index 0000000..5736430 --- /dev/null +++ b/src/ast.rs @@ -0,0 +1,69 @@ +use std::collections::HashMap; + +use crate::Integer; + +/// Store for input declarations +pub type Inputs = HashMap; + +/// Top level ast object +#[derive(Debug, Clone)] +pub struct Root { + /// Raw inputs + pub inputs: Inputs, + /// Top level object, values aren't interpolated + pub object: Object, +} + +/// Represents an object in the AST +#[derive(Debug, Clone)] +pub struct Object { + // /// The pairs or spread operations in the object + pub pairs: Vec, +} + +/// Either a key-value pair or a spread operation +#[derive(Debug, Clone)] +pub enum PairOrSpread { + /// A key-value pair in an object + Pair(ChainedKey, Entry), + /// A spread operation in an object + Spread(String), +} + +/// An entry can be of various types as defined in the spec +#[derive(Debug, Clone)] +pub enum Entry { + /// String literal + String(String), + /// Integer value + Integer(Integer), + /// Float value + Float(f64), + /// Boolean value + Boolean(bool), + /// Nested object + Object(Object), + /// Array of entries + Array(Vec), + /// Null value + Null, + /// Reference to an input variable + Input(String), + /// Array spread operation + Spread(String), +} + +/// Represents a chained key like "foo.bar.baz" +#[derive(Debug, Clone)] +pub struct ChainedKey { + /// The segments of the key path + pub segments: Vec, +} + +impl ChainedKey { + pub fn new(key: String) -> Self { + Self { + segments: vec![key], + } + } +} diff --git a/src/corn.lalrpop b/src/corn.lalrpop new file mode 100644 index 0000000..8159a4f --- /dev/null +++ b/src/corn.lalrpop @@ -0,0 +1,87 @@ +use crate::ast::{Root, Entry, Object, Inputs, PairOrSpread, ChainedKey}; +use crate::lexer::{LexicalError, Token}; +use crate::Integer; + +grammar; + +extern { + type Location = usize; + type Error = LexicalError; + + enum Token { + "let" => Token::Let, + "in" => Token::In, + "null" => Token::Null, + "=" => Token::Equals, + "{" => Token::OpenBrace, + "}" => Token::CloseBrace, + "[" => Token::OpenBracket, + "]" => Token::CloseBracket, + "." => Token::Chain, + ".." => Token::Spread, + "literal" => Token::StringLiteral(), + "int" => Token::Integer(), + "float" => Token::Float(), + "bool" => Token::Boolean(), + "input" => Token::InputName(), + "key" => Token::Key(), + } +} + +pub Root: Root = { + => { + Root { + inputs: inputs.unwrap_or_default(), + object, + } + } +} + +LetBlock: Inputs = { + "let" "{" )*> "}" "in" => inputs.into_iter().collect() +}; + +InputDeclaration: (String, Entry) = { + "=" => (name, entry), +}; + +Entry: Entry = { + "literal" => Entry::String(<>), + "int" => Entry::Integer(<>), + "float" => Entry::Float(<>), + "bool" => Entry::Boolean(<>), + Object => Entry::Object(<>), + Array => Entry::Array(<>), + "null" => Entry::Null, + "input" => Entry::Input(<>), +} + +Object: Object = { + "{" )*> "}" => { + Object { + pairs, + } + } +}; + +Pair: PairOrSpread = { + "=" => PairOrSpread::Pair(k, v), + ".." => PairOrSpread::Spread(name), +}; + +KeyPath: ChainedKey = { + )*> => { + ChainedKey { + segments: [vec![first], rest].concat() + } + } +}; + +Array: Vec = { + "[" "]" => entries, +}; + +ArrayEntry: Entry = { + Entry => <>, + ".." => Entry::Spread(name), +}; \ No newline at end of file diff --git a/src/de.rs b/src/de.rs deleted file mode 100644 index 8cade85..0000000 --- a/src/de.rs +++ /dev/null @@ -1,543 +0,0 @@ -use std::collections::VecDeque; - -use serde::de::{self, DeserializeSeed, EnumAccess, IntoDeserializer, VariantAccess, Visitor}; - -use crate::error::{Error, Result}; -use crate::parse; -use crate::Value; - -#[derive(Debug)] -pub struct Deserializer<'de> { - value: Option>, -} - -impl<'de> Deserializer<'de> { - pub fn from_str(input: &'de str) -> Result { - let parsed = parse(input)?; - - Ok(Self::from_value(parsed)) - } - - fn from_value(value: Value<'de>) -> Self { - Self { value: Some(value) } - } -} - -/// Attempts to deserialize the config from a string slice. -/// -/// # Errors -/// -/// Will return a `DeserializationError` if the config is invalid. -pub fn from_str(s: &str) -> Result -where - T: de::DeserializeOwned, -{ - let mut deserializer = Deserializer::from_str(s)?; - T::deserialize(&mut deserializer) -} - -/// Attempts to deserialize the config from a byte slice. -/// -/// # Errors -/// -/// Will return a `DeserializationError` if the config is invalid. -pub fn from_slice(bytes: &[u8]) -> Result -where - T: de::DeserializeOwned, -{ - match std::str::from_utf8(bytes) { - Ok(s) => from_str(s), - Err(e) => Err(Error::DeserializationError(e.to_string())), - } -} - -macro_rules! get_value { - ($self:ident) => { - match $self.value.take() { - Some(val) => Ok(val), - None => Err(Error::DeserializationError(String::from( - "Deserializer value unexpectedly `None`", - ))), - }? - }; -} - -macro_rules! err_expected { - ($expected:literal, $got:expr) => { - Err(Error::DeserializationError(format!( - "Expected {}, found '{:?}'", - $expected, $got - ))) - }; -} - -macro_rules! match_value { - ($self:ident, $name:literal, $($pat:pat => $expr:expr)+) => {{ - let value = get_value!($self); - match value { - $($pat => $expr, )+ - _ => err_expected!($name, value) - } - }}; -} - -impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { - type Error = Error; - - fn deserialize_any(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - let value = get_value!(self); - match value { - Value::Object(_) => { - let map = Map::new(value); - visitor.visit_map(map) - } - Value::Array(_) => { - let seq = Seq::new(value); - visitor.visit_seq(seq) - } - Value::String(val) => visitor.visit_str(&val), - Value::Integer(val) => visitor.visit_i64(val), - Value::Float(val) => visitor.visit_f64(val), - Value::Boolean(val) => visitor.visit_bool(val), - Value::Null(_) => visitor.visit_unit(), - } - } - - fn deserialize_bool(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - match_value!(self, "boolean", Value::Boolean(val) => visitor.visit_bool(val)) - } - - fn deserialize_i8(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - match_value!(self, "integer (i8)", Value::Integer(val) => visitor.visit_i8(val as i8)) - } - - fn deserialize_i16(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - match_value!(self, "integer (i16)", Value::Integer(val) => visitor.visit_i16(val as i16)) - } - - fn deserialize_i32(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - match_value!(self, "integer (i32)", Value::Integer(val) => visitor.visit_i32(val as i32)) - } - - fn deserialize_i64(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - match_value!(self, "integer (i64)", Value::Integer(val) => visitor.visit_i64(val)) - } - - fn deserialize_u8(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - match_value!(self, "integer (u8)", Value::Integer(val) => visitor.visit_u8(val as u8)) - } - - fn deserialize_u16(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - match_value!(self, "integer (u16)", Value::Integer(val) => visitor.visit_u16(val as u16)) - } - - fn deserialize_u32(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - match_value!(self, "integer (u32)", Value::Integer(val) => visitor.visit_u32(val as u32)) - } - - fn deserialize_u64(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - match_value!(self, "integer (u64)", Value::Integer(val) => visitor.visit_u64(val as u64)) - } - - fn deserialize_f32(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - match_value!(self, "float (f32)", Value::Float(val) => visitor.visit_f32(val as f32)) - } - - fn deserialize_f64(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - match_value!(self, "float (f64)", Value::Float(val) => visitor.visit_f64(val)) - } - - fn deserialize_char(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - let value = get_value!(self); - let char = match value { - Value::String(value) => value.chars().next(), - _ => return err_expected!("char", value), - }; - - match char { - Some(char) => visitor.visit_char(char), - None => err_expected!("char", "empty string"), - } - } - - fn deserialize_str(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - match_value!(self, "string", - Value::String(val) => visitor.visit_str(&val) - ) - } - - fn deserialize_string(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - self.deserialize_str(visitor) - } - - fn deserialize_bytes(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - match_value!(self, "bytes array", - Value::String(val) => visitor.visit_bytes(val.as_bytes()) - ) - } - - fn deserialize_byte_buf(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - self.deserialize_bytes(visitor) - } - - fn deserialize_option(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - let value = get_value!(self); - match value { - Value::Null(_) => visitor.visit_none(), - _ => visitor.visit_some(&mut Deserializer::from_value(value)), - } - } - - fn deserialize_unit(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - visitor.visit_unit() - } - - fn deserialize_unit_struct( - self, - _name: &'static str, - visitor: V, - ) -> std::result::Result - where - V: Visitor<'de>, - { - self.deserialize_unit(visitor) - } - - fn deserialize_newtype_struct( - self, - _name: &'static str, - visitor: V, - ) -> std::result::Result - where - V: Visitor<'de>, - { - visitor.visit_newtype_struct(self) - } - - fn deserialize_seq(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - let value = get_value!(self); - match value { - Value::Array(_) => visitor.visit_seq(Seq::new(value)), - _ => err_expected!("array", value), - } - } - - fn deserialize_tuple( - self, - _len: usize, - visitor: V, - ) -> std::result::Result - where - V: Visitor<'de>, - { - self.deserialize_seq(visitor) - } - - fn deserialize_tuple_struct( - self, - _name: &'static str, - _len: usize, - visitor: V, - ) -> std::result::Result - where - V: Visitor<'de>, - { - self.deserialize_seq(visitor) - } - - fn deserialize_map(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - let value = get_value!(self); - match value { - Value::Object(_) => visitor.visit_map(Map::new(value)), - _ => err_expected!("object", value), - } - } - - fn deserialize_struct( - self, - _name: &'static str, - _fields: &'static [&'static str], - visitor: V, - ) -> std::result::Result - where - V: Visitor<'de>, - { - self.deserialize_map(visitor) - } - - fn deserialize_enum( - self, - _name: &'static str, - _variants: &'static [&'static str], - visitor: V, - ) -> std::result::Result - where - V: Visitor<'de>, - { - let value = get_value!(self); - match value { - Value::Object(_) => visitor.visit_enum(Enum::new(value)), - Value::String(val) => visitor.visit_enum(val.into_deserializer()), - _ => err_expected!("object or string (enum variant)", value), - } - } - - fn deserialize_identifier(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - self.deserialize_str(visitor) - } - - fn deserialize_ignored_any(self, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - self.deserialize_any(visitor) - } -} - -struct Map<'de> { - values: VecDeque>, -} - -impl<'de> Map<'de> { - fn new(value: Value<'de>) -> Self { - match value { - Value::Object(values) => Self { - values: values - .into_iter() - .flat_map(|(key, value)| vec![Value::String(key), value]) - .collect(), - }, - _ => unreachable!(), - } - } -} - -impl<'de> de::MapAccess<'de> for Map<'de> { - type Error = Error; - - fn next_key_seed(&mut self, seed: K) -> std::result::Result, Self::Error> - where - K: DeserializeSeed<'de>, - { - if let Some(value) = self.values.pop_front() { - seed.deserialize(&mut Deserializer::from_value(value)) - .map(Some) - } else { - Ok(None) - } - } - - fn next_value_seed(&mut self, seed: V) -> std::result::Result - where - V: DeserializeSeed<'de>, - { - match self.values.pop_front() { - Some(value) => seed.deserialize(&mut Deserializer::from_value(value)), - None => Err(Error::DeserializationError( - "Expected value to exist".to_string(), - )), - } - } - - fn size_hint(&self) -> Option { - Some(self.values.len() / 2) - } -} - -struct Seq<'de> { - values: VecDeque>, -} - -impl<'de> Seq<'de> { - fn new(value: Value<'de>) -> Self { - match value { - Value::Array(values) => Self { - values: VecDeque::from(values), - }, - _ => unreachable!(), - } - } -} - -impl<'de> de::SeqAccess<'de> for Seq<'de> { - type Error = Error; - - fn next_element_seed( - &mut self, - seed: T, - ) -> std::result::Result, Self::Error> - where - T: DeserializeSeed<'de>, - { - if let Some(value) = self.values.pop_front() { - seed.deserialize(&mut Deserializer::from_value(value)) - .map(Some) - } else { - Ok(None) - } - } - - fn size_hint(&self) -> Option { - Some(self.values.len()) - } -} - -struct Enum<'de> { - value: Value<'de>, -} - -impl<'de> Enum<'de> { - fn new(value: Value<'de>) -> Self { - Self { value } - } -} - -impl<'de> EnumAccess<'de> for Enum<'de> { - type Error = Error; - type Variant = Variant<'de>; - - fn variant_seed(self, seed: V) -> std::result::Result<(V::Value, Self::Variant), Self::Error> - where - V: DeserializeSeed<'de>, - { - match self.value { - Value::String(_) => { - let value = seed.deserialize(&mut Deserializer::from_value(self.value))?; - Ok((value, Variant::new(None))) - } - Value::Object(obj) => { - let first_pair = obj.into_iter().next(); - if let Some(first_pair) = first_pair { - let value = Value::String(first_pair.0); - let tag = seed.deserialize(&mut Deserializer::from_value(value))?; - Ok((tag, Variant::new(Some(first_pair.1)))) - } else { - Err(Error::DeserializationError( - "Cannot deserialize empty object into enum".to_string(), - )) - } - } - _ => unreachable!(), - } - } -} - -struct Variant<'de> { - value: Option>, -} - -impl<'de> Variant<'de> { - fn new(value: Option>) -> Self { - Self { value } - } -} - -impl<'de> VariantAccess<'de> for Variant<'de> { - type Error = Error; - - fn unit_variant(self) -> std::result::Result<(), Self::Error> { - Ok(()) - } - - fn newtype_variant_seed(self, seed: T) -> std::result::Result - where - T: DeserializeSeed<'de>, - { - match self.value { - Some(value) => seed.deserialize(&mut Deserializer::from_value(value)), - None => Err(Error::DeserializationError( - "Expected value to exist".to_string(), - )), - } - } - - fn tuple_variant(self, _len: usize, visitor: V) -> std::result::Result - where - V: Visitor<'de>, - { - match self.value { - Some(value) if matches!(value, Value::Array(_)) => visitor.visit_seq(Seq::new(value)), - _ => unreachable!(), - } - } - - fn struct_variant( - self, - _fields: &'static [&'static str], - visitor: V, - ) -> std::result::Result - where - V: Visitor<'de>, - { - match self.value { - Some(value) if matches!(value, Value::Object(_)) => visitor.visit_map(Map::new(value)), - _ => unreachable!(), - } - } -} diff --git a/src/lexer.rs b/src/lexer.rs index 36962d5..d24c61b 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -81,27 +81,37 @@ pub enum Token { #[token("..")] Spread, - #[regex(r#""[^"]*""#, |lex| lex.slice().trim_matches('"').to_string())] - StringLiteral(String), + #[token("false", |_| false)] + #[token("true", |_| true)] + Boolean(bool), #[regex(r"-[0-9]+(_[0-9]+)*", |lex| lex.slice().replace("_", "").parse::().map(Integer::from))] #[regex(r"[0-9]+(_[0-9]+)*", |lex| lex.slice().replace("_", "").parse::().map(Integer::from))] + // FIXME: this is a mess sob + #[regex(r"0x[0-9a-fA-F][_0-9a-fA-F]*", |lex| i64::from_str_radix(&lex.slice().trim_start_matches("0x").replace("_", ""), 16).map(Integer::from))] Integer(Integer), #[regex(r"-?[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?", |lex| lex.slice().parse::())] Float(f64), - #[token("false", |_| false)] - #[token("true", |_| true)] - Boolean(bool), - #[regex(r"\$[a-zA-Z_][a-zA-Z0-9_]*", |lex| lex.slice().to_string())] InputName(String), - #[regex(r"'[^']*'|[^\s.=0-9\[\]{}-][^\s.=]*", |lex| lex.slice().trim_matches('\'').to_string())] + #[regex(r#""(?:[^"\\]|\\[\\\"nrt$]|\\u[0-9a-fA-F]{4})*""#, |lex| lex.slice().trim_matches('"').to_string())] + StringLiteral(String), + + InterpolatedString(Vec), // FIXME: parse interpolated strings + + #[regex(r#"'(?:[^'\\]|\\.)*'|[^\s.=0-9\[\]{}"'][^\s.=\[\]{}"']*"#, |lex| lex.slice().trim_matches('\'').to_string())] Key(String), } +#[derive(Debug, Clone, PartialEq)] +pub enum StringPart { + Literal(String), + Input(String), +} + impl fmt::Display for Token { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -116,6 +126,16 @@ impl fmt::Display for Token { Self::Chain => write!(f, "."), Self::Spread => write!(f, ".."), Self::StringLiteral(lit) => lit.fmt(f), + Self::InterpolatedString(parts) => { + for part in parts { + match part { + StringPart::Literal(lit) => write!(f, "{lit}")?, + StringPart::Input(input) => write!(f, "${input}")?, + } + } + + Ok(()) + } Self::Integer(int) => int.fmt(f), Self::Float(float) => float.fmt(f), Self::Boolean(bool) => bool.fmt(f), diff --git a/src/lib.rs b/src/lib.rs index ab9dde5..0832fc7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,54 +23,30 @@ // #[cfg(feature = "wasm")] // mod wasm; -// /// A map of input names and values. -// /// The names include their `$` prefix. -// pub type Inputs<'a> = HashMap<&'a str, Value<'a>>; -// /// A map of keys to their values. -// pub type Object<'a> = IndexMap, Value<'a>>; +lalrpop_util::lalrpop_mod!(pub parser, "/corn.rs"); -// #[derive(Serialize, Debug, Clone)] -// #[serde(untagged)] -// pub enum Value<'a> { -// /// Key/value map. Values can be mixed types. -// Object(Object<'a>), -// /// Array of values, can be mixed types. -// Array(Vec>), -// /// UTF-8 string -// String(Cow<'a, str>), -// /// 64-bit signed integer. -// Integer(i64), -// /// 64-bit (double precision) floating point number. -// Float(f64), -// /// true or false -// Boolean(bool), -// /// `null` literal. -// /// -// /// Takes an optional unit type as the `toml` crate -// /// errors when encountering unit types, -// /// but can handle `None` types. -// Null(Option<()>), -// } - -// impl Display for Value<'_> { -// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { -// write!( -// f, -// "{}", -// match self { -// Value::Object(_) => "object", -// Value::Array(_) => "array", -// Value::String(_) => "string", -// Value::Integer(_) => "integer", -// Value::Float(_) => "float", -// Value::Boolean(_) => "boolean", -// Value::Null(_) => "null", -// } -// ) -// } -// } mod value; -pub use value::{Object, Value, Integer}; \ No newline at end of file +pub mod ast; +pub mod lexer; + +use std::fmt::Display; + +pub use value::{Integer, Object, Value}; + +#[derive(Debug)] +pub struct Error; + +impl Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + todo!() + } +} + +impl std::error::Error for Error {} + +pub fn parse(file: &str) -> Result { + todo!() +} From 24926a0bcb36f8779b3b5bc5b95a32ba7e5cb588 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 17 Jun 2025 12:12:08 +0200 Subject: [PATCH 08/68] Expose error to library root --- src/error.rs | 27 ++++++++++++--------------- src/lib.rs | 21 ++++----------------- 2 files changed, 16 insertions(+), 32 deletions(-) diff --git a/src/error.rs b/src/error.rs index cf0e631..24d48de 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,30 +1,27 @@ -use std::fmt::{Debug, Display}; +use std::fmt::Display; use thiserror::Error; -use crate::Rule; - -pub type Result = std::result::Result; +pub type Result = std::result::Result; #[derive(Error, Debug)] pub enum Error { #[error(transparent)] Io(#[from] std::io::Error), - #[error(transparent)] - ParserError(#[from] Box>), - - #[error("failed to resolve referenced input `{0}`")] - InputResolveError(String), + // #[error(transparent)] + // ParserError(#[from] Box>), - #[error("attempted to use dot-notation on non-object value at `{0}`")] - InvalidPathError(String), + // #[error("failed to resolve referenced input `{0}`")] + // InputResolveError(String), - #[error("attempted to spread a type that differs from its containing type at `{0}`")] - InvalidSpreadError(String), + // #[error("attempted to use dot-notation on non-object value at `{0}`")] + // InvalidPathError(String), - #[error("attempted to interpolate a non-string type into a string at `{0}`")] - InvalidInterpolationError(String), + // #[error("attempted to spread a type that differs from its containing type at `{0}`")] + // InvalidSpreadError(String), + // #[error("attempted to interpolate a non-string type into a string at `{0}`")] + // InvalidInterpolationError(String), #[error("failed to deserialize input: {0}")] DeserializationError(String), } diff --git a/src/lib.rs b/src/lib.rs index 0832fc7..21118e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,6 @@ // pub use crate::de::{from_slice, from_str}; // pub use crate::parser::{parse, Rule}; -// pub mod error; // mod parser; // mod de; @@ -23,30 +22,18 @@ // #[cfg(feature = "wasm")] // mod wasm; - lalrpop_util::lalrpop_mod!(pub parser, "/corn.rs"); - +mod error; mod value; +pub use error::{Error, Result}; + pub mod ast; pub mod lexer; -use std::fmt::Display; - pub use value::{Integer, Object, Value}; -#[derive(Debug)] -pub struct Error; - -impl Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - todo!() - } -} - -impl std::error::Error for Error {} - -pub fn parse(file: &str) -> Result { +pub fn parse(_file: &str) -> Result { todo!() } From c9bdf52b1db0186cff303d3b40c7b5d07552f570 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 17 Jun 2025 13:31:42 +0200 Subject: [PATCH 09/68] Mark integer as repr transparent --- src/value/integer.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/value/integer.rs b/src/value/integer.rs index 5d2063e..e71be42 100644 --- a/src/value/integer.rs +++ b/src/value/integer.rs @@ -2,6 +2,7 @@ use serde::Serialize; use std::fmt::{Debug, Display}; #[derive(PartialEq, Eq, PartialOrd, Ord, Clone)] +#[repr(transparent)] pub struct Integer { inner: IntegerType, } From 80abd83ce44aa1623cf5cd9e3ce690ab98e20ac0 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 17 Jun 2025 13:42:49 +0200 Subject: [PATCH 10/68] Make the lexer and parser borrow the input --- src/ast.rs | 42 +++++++++++++++++------------------------- src/corn.lalrpop | 28 ++++++++++++++-------------- src/lexer.rs | 21 ++++++++++----------- 3 files changed, 41 insertions(+), 50 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 5736430..f5617f7 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -3,38 +3,38 @@ use std::collections::HashMap; use crate::Integer; /// Store for input declarations -pub type Inputs = HashMap; +pub type Inputs<'input> = HashMap<&'input str, Entry<'input>>; /// Top level ast object #[derive(Debug, Clone)] -pub struct Root { +pub struct Root<'input> { /// Raw inputs - pub inputs: Inputs, + pub inputs: Inputs<'input>, /// Top level object, values aren't interpolated - pub object: Object, + pub object: Object<'input>, } /// Represents an object in the AST #[derive(Debug, Clone)] -pub struct Object { +pub struct Object<'input> { // /// The pairs or spread operations in the object - pub pairs: Vec, + pub pairs: Vec>, } /// Either a key-value pair or a spread operation #[derive(Debug, Clone)] -pub enum PairOrSpread { +pub enum PairOrSpread<'input> { /// A key-value pair in an object - Pair(ChainedKey, Entry), + Pair(ChainedKey<'input>, Entry<'input>), /// A spread operation in an object - Spread(String), + Spread(&'input str), } /// An entry can be of various types as defined in the spec #[derive(Debug, Clone)] -pub enum Entry { +pub enum Entry<'input> { /// String literal - String(String), + String(&'input str), /// Integer value Integer(Integer), /// Float value @@ -42,28 +42,20 @@ pub enum Entry { /// Boolean value Boolean(bool), /// Nested object - Object(Object), + Object(Object<'input>), /// Array of entries - Array(Vec), + Array(Vec>), /// Null value Null, /// Reference to an input variable - Input(String), + Input(&'input str), /// Array spread operation - Spread(String), + Spread(&'input str), } /// Represents a chained key like "foo.bar.baz" #[derive(Debug, Clone)] -pub struct ChainedKey { +pub struct ChainedKey<'input> { /// The segments of the key path - pub segments: Vec, -} - -impl ChainedKey { - pub fn new(key: String) -> Self { - Self { - segments: vec![key], - } - } + pub segments: Vec<&'input str>, } diff --git a/src/corn.lalrpop b/src/corn.lalrpop index 8159a4f..86b5ce3 100644 --- a/src/corn.lalrpop +++ b/src/corn.lalrpop @@ -2,13 +2,13 @@ use crate::ast::{Root, Entry, Object, Inputs, PairOrSpread, ChainedKey}; use crate::lexer::{LexicalError, Token}; use crate::Integer; -grammar; +grammar<'input>(input: &'input str); extern { type Location = usize; type Error = LexicalError; - enum Token { + enum Token<'input> { "let" => Token::Let, "in" => Token::In, "null" => Token::Null, @@ -19,16 +19,16 @@ extern { "]" => Token::CloseBracket, "." => Token::Chain, ".." => Token::Spread, - "literal" => Token::StringLiteral(), + "literal" => Token::StringLiteral(<&'input str>), "int" => Token::Integer(), "float" => Token::Float(), "bool" => Token::Boolean(), - "input" => Token::InputName(), - "key" => Token::Key(), + "input" => Token::InputName(<&'input str>), + "key" => Token::Key(<&'input str>), } } -pub Root: Root = { +pub Root: Root<'input> = { => { Root { inputs: inputs.unwrap_or_default(), @@ -37,15 +37,15 @@ pub Root: Root = { } } -LetBlock: Inputs = { +LetBlock: Inputs<'input> = { "let" "{" )*> "}" "in" => inputs.into_iter().collect() }; -InputDeclaration: (String, Entry) = { +InputDeclaration: (&'input str, Entry<'input>) = { "=" => (name, entry), }; -Entry: Entry = { +Entry: Entry<'input> = { "literal" => Entry::String(<>), "int" => Entry::Integer(<>), "float" => Entry::Float(<>), @@ -56,7 +56,7 @@ Entry: Entry = { "input" => Entry::Input(<>), } -Object: Object = { +Object: Object<'input> = { "{" )*> "}" => { Object { pairs, @@ -64,12 +64,12 @@ Object: Object = { } }; -Pair: PairOrSpread = { +Pair: PairOrSpread<'input> = { "=" => PairOrSpread::Pair(k, v), ".." => PairOrSpread::Spread(name), }; -KeyPath: ChainedKey = { +KeyPath: ChainedKey<'input> = { )*> => { ChainedKey { segments: [vec![first], rest].concat() @@ -77,11 +77,11 @@ KeyPath: ChainedKey = { } }; -Array: Vec = { +Array: Vec> = { "[" "]" => entries, }; -ArrayEntry: Entry = { +ArrayEntry: Entry<'input> = { Entry => <>, ".." => Entry::Spread(name), }; \ No newline at end of file diff --git a/src/lexer.rs b/src/lexer.rs index d24c61b..2fbe545 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -12,12 +12,11 @@ pub type Spanned = Result<(Loc, Tok, Loc), Error>; pub struct Lexer<'input> { // instead of an iterator over characters, we have a token iterator - token_stream: SpannedIter<'input, Token>, + token_stream: SpannedIter<'input, Token<'input>>, } impl<'input> Lexer<'input> { pub fn new(input: &'input str) -> Self { - // the Token::lexer() method is provided by the Logos trait Self { token_stream: Token::lexer(input).spanned(), } @@ -25,7 +24,7 @@ impl<'input> Lexer<'input> { } impl<'input> Iterator for Lexer<'input> { - type Item = Spanned; + type Item = Spanned, usize, LexicalError>; fn next(&mut self) -> Option { self.token_stream @@ -50,7 +49,7 @@ pub enum LexicalError { #[logos(skip r"[\s\t\r\n\f]+")] // Whitespace #[logos(skip r"//[^\n\r]*[\n\r]*")] // Inline comments #[logos(skip r"/\*([^*/]|\*[^/]|/[^*])*\*/")] // Multiline comments -pub enum Token { +pub enum Token<'input> { #[token("let")] Let, @@ -94,16 +93,16 @@ pub enum Token { #[regex(r"-?[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?", |lex| lex.slice().parse::())] Float(f64), - #[regex(r"\$[a-zA-Z_][a-zA-Z0-9_]*", |lex| lex.slice().to_string())] - InputName(String), + #[regex(r"\$[a-zA-Z_][a-zA-Z0-9_]*", |lex| lex.slice())] + InputName(&'input str), - #[regex(r#""(?:[^"\\]|\\[\\\"nrt$]|\\u[0-9a-fA-F]{4})*""#, |lex| lex.slice().trim_matches('"').to_string())] - StringLiteral(String), + #[regex(r#""(?:[^"\\]|\\[\\\"nrt$]|\\u[0-9a-fA-F]{4})*""#, |lex| lex.slice().trim_matches('"'))] + StringLiteral(&'input str), InterpolatedString(Vec), // FIXME: parse interpolated strings - #[regex(r#"'(?:[^'\\]|\\.)*'|[^\s.=0-9\[\]{}"'][^\s.=\[\]{}"']*"#, |lex| lex.slice().trim_matches('\'').to_string())] - Key(String), + #[regex(r#"'(?:[^'\\]|\\.)*'|[^\s.=0-9\[\]{}"'][^\s.=\[\]{}"']*"#, |lex| lex.slice().trim_matches('\''))] + Key(&'input str), } #[derive(Debug, Clone, PartialEq)] @@ -112,7 +111,7 @@ pub enum StringPart { Input(String), } -impl fmt::Display for Token { +impl fmt::Display for Token<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Let => write!(f, "let"), From 47eec3141a59d3b02500f7f57c5f50707bf8ad8c Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 17 Jun 2025 13:54:49 +0200 Subject: [PATCH 11/68] Implement deserialize skeleton and fix lua --- src/de.rs | 253 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 44 +++------- src/lua.rs | 4 +- 3 files changed, 268 insertions(+), 33 deletions(-) create mode 100644 src/de.rs diff --git a/src/de.rs b/src/de.rs new file mode 100644 index 0000000..513f694 --- /dev/null +++ b/src/de.rs @@ -0,0 +1,253 @@ +use serde::{de, forward_to_deserialize_any, Deserialize}; + +use crate::{Error, Result}; + +#[derive(Clone)] +pub struct Deserializer<'de> { + bytes: &'de [u8], +} + +impl<'de> Deserializer<'de> { + /// Refer to the `Deserializer::from_str` method for more info. + pub fn from_str(input: &'de str) -> Result { + todo!() + } +} +pub fn from_str<'a, T>(s: &'a str) -> Result +where + T: de::Deserialize<'a>, +{ + let mut deserializer = Deserializer::from_str(s)?; + + T::deserialize(&mut deserializer) +} + +impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { + type Error = Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_bool(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_i8(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_i16(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_i32(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_i64(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_u8(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_u16(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_u32(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_u64(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_f32(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_f64(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_char(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_str(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_string(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_bytes(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_byte_buf(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_option(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_unit(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_unit_struct( + self, + name: &'static str, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_newtype_struct( + self, + name: &'static str, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_seq(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_tuple(self, len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_tuple_struct( + self, + name: &'static str, + len: usize, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_map(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_struct( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_enum( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_identifier(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } + + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + todo!() + } +} diff --git a/src/lib.rs b/src/lib.rs index 21118e6..b001dbb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,39 +1,21 @@ -// use indexmap::IndexMap; -// use serde::Serialize; -// use std::borrow::Cow; -// use std::collections::HashMap; -// use std::fmt::{Display, Formatter}; - -// pub use crate::de::{from_slice, from_str}; -// pub use crate::parser::{parse, Rule}; - -// mod parser; - -// mod de; -// #[cfg(any( -// feature = "lua51", -// feature = "lua52", -// feature = "lua53", -// feature = "lua54", -// feature = "luajit", -// feature = "luajit52" -// ))] -// mod lua; -// #[cfg(feature = "wasm")] -// mod wasm; - -lalrpop_util::lalrpop_mod!(pub parser, "/corn.rs"); +mod de; +#[cfg(any( + feature = "lua51", + feature = "lua52", + feature = "lua53", + feature = "lua54", + feature = "luajit", + feature = "luajit52" +))] +mod lua; mod error; mod value; -pub use error::{Error, Result}; - pub mod ast; pub mod lexer; +lalrpop_util::lalrpop_mod!(pub parser, "/corn.rs"); +pub use de::{from_str, Deserializer}; +pub use error::{Error, Result}; pub use value::{Integer, Object, Value}; - -pub fn parse(_file: &str) -> Result { - todo!() -} diff --git a/src/lua.rs b/src/lua.rs index 539b992..c6ae350 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -1,14 +1,14 @@ use crate::Value; use mlua::prelude::*; -impl IntoLua for Value<'_> { +impl IntoLua for Value { fn into_lua(self, lua: &Lua) -> LuaResult { lua.to_value(&self) } } fn lua_parse(lua: &Lua, config: String) -> LuaResult { - let res = crate::parse(&config); + let res = crate::from_str::(&config); match res { Ok(v) => Ok(lua.to_value(&v)?), Err(e) => Err(LuaError::RuntimeError(e.to_string())), From 934bf893d010ca2369205f5dab48a81b11ebc267 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 17 Jun 2025 21:26:20 +0200 Subject: [PATCH 12/68] Parse array spreads only inside arrays --- src/ast.rs | 21 ++++++++++++++------- src/corn.lalrpop | 10 +++++----- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index f5617f7..00f70eb 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -30,6 +30,13 @@ pub enum PairOrSpread<'input> { Spread(&'input str), } +/// Represents a chained key like "foo.bar.baz" +#[derive(Debug, Clone)] +pub struct ChainedKey<'input> { + /// The segments of the key path + pub segments: Vec<&'input str>, +} + /// An entry can be of various types as defined in the spec #[derive(Debug, Clone)] pub enum Entry<'input> { @@ -44,18 +51,18 @@ pub enum Entry<'input> { /// Nested object Object(Object<'input>), /// Array of entries - Array(Vec>), + Array(Vec>), /// Null value Null, /// Reference to an input variable Input(&'input str), - /// Array spread operation - Spread(&'input str), } -/// Represents a chained key like "foo.bar.baz" +/// Either a key or an array spread operation #[derive(Debug, Clone)] -pub struct ChainedKey<'input> { - /// The segments of the key path - pub segments: Vec<&'input str>, +pub enum EntryOrSpread<'input> { + /// An entry can be of various types as defined in the spec + Entry(Entry<'input>), + /// Array spread operation + Spread(&'input str), } diff --git a/src/corn.lalrpop b/src/corn.lalrpop index 86b5ce3..c247c10 100644 --- a/src/corn.lalrpop +++ b/src/corn.lalrpop @@ -1,4 +1,4 @@ -use crate::ast::{Root, Entry, Object, Inputs, PairOrSpread, ChainedKey}; +use crate::ast::{Root, Entry, Object, Inputs, PairOrSpread, ChainedKey, EntryOrSpread}; use crate::lexer::{LexicalError, Token}; use crate::Integer; @@ -77,11 +77,11 @@ KeyPath: ChainedKey<'input> = { } }; -Array: Vec> = { +Array: Vec> = { "[" "]" => entries, }; -ArrayEntry: Entry<'input> = { - Entry => <>, - ".." => Entry::Spread(name), +ArrayEntry: EntryOrSpread<'input> = { + Entry => EntryOrSpread::Entry(<>), + ".." => EntryOrSpread::Spread(name), }; \ No newline at end of file From 0ba6c8fa9992424f868845fcb840d294ccb71bb3 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 17 Jun 2025 21:26:45 +0200 Subject: [PATCH 13/68] Implement most of the deserializer --- src/de.rs | 444 +++++++++++++++++++++++-------------------- src/lib.rs | 2 +- src/value/integer.rs | 8 +- src/value/mod.rs | 1 + 4 files changed, 248 insertions(+), 207 deletions(-) diff --git a/src/de.rs b/src/de.rs index 513f694..af7e023 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1,18 +1,173 @@ -use serde::{de, forward_to_deserialize_any, Deserialize}; +use std::borrow::Cow; -use crate::{Error, Result}; +use indexmap::IndexMap; +use serde::{de, forward_to_deserialize_any}; + +use crate::{ + ast::{Entry, EntryOrSpread, Inputs, PairOrSpread, Root}, + lexer::Lexer, + parser::RootParser, + value::IntegerType, + Error, Integer, Result, +}; #[derive(Clone)] pub struct Deserializer<'de> { - bytes: &'de [u8], + entry: ResolvedEntry<'de>, +} + +#[derive(Clone)] +enum ResolvedEntry<'input> { + String(Cow<'input, str>), + Integer(Integer), + Float(f64), + Boolean(bool), + Null, + Array(Vec>), + Object(IndexMap<&'input str, ResolvedEntry<'input>>), } impl<'de> Deserializer<'de> { /// Refer to the `Deserializer::from_str` method for more info. pub fn from_str(input: &'de str) -> Result { - todo!() + let mut lexer = Lexer::new(input); + let parser = RootParser::new(); + let Root { inputs, object } = parser.parse(input, &mut lexer).expect("Failed to parse"); // FIXME: handler errors + + Ok(Self { + entry: Self::resolve_entry(&Entry::Object(object), &inputs)?, + }) + } + + fn with_entry(entry: ResolvedEntry<'de>) -> Self { + Self { entry } + } + + fn resolve_entry<'input>( + entry: &Entry<'input>, + inputs: &Inputs<'input>, + ) -> Result> { + match entry { + Entry::String(s) => Ok(ResolvedEntry::String(Cow::Borrowed(s))), // TODO: handle interpolation here or at lexer level? + Entry::Integer(integer) => Ok(ResolvedEntry::Integer(*integer)), + Entry::Float(float) => Ok(ResolvedEntry::Float(*float)), + Entry::Boolean(boolean) => Ok(ResolvedEntry::Boolean(*boolean)), + Entry::Object(obj) => { + let mut resolved_object = IndexMap::new(); + + for pair_or_spread in &obj.pairs { + match pair_or_spread { + PairOrSpread::Pair(key, value) => { + Self::insert_at_path( + &mut resolved_object, + &key.segments, + Self::resolve_entry(value, inputs)?, + )?; + } + PairOrSpread::Spread(name) => { + if let Some(spread_entry) = inputs.get(name) { + match Self::resolve_entry(spread_entry, inputs)? { + ResolvedEntry::Object(spread_obj) => { + for (k, v) in spread_obj { + resolved_object.insert(k, v); + } + } + _ => { + return Err(Error::DeserializationError(format!( + "Cannot spread non-object type: {}", + name + ))) + } + } + } else { + return Err(Error::DeserializationError(format!( + "Undefined input for spread: {}", + name + ))); + } + } + } + } + + Ok(ResolvedEntry::Object(resolved_object)) + } + Entry::Array(items) => { + let mut resolved_array = Vec::with_capacity(items.len()); // We need at least the same amount of items + + for entry in items { + match entry { + EntryOrSpread::Entry(entry) => { + resolved_array.push(Self::resolve_entry(entry, inputs)?) + } + EntryOrSpread::Spread(spread) => match Self::resolve_input(spread, inputs)? + { + ResolvedEntry::Array(array) => { + resolved_array.extend(array); + } + _ => panic!("Only arrays support being spreaded"), // FIXME: return an error + }, + } + } + + Ok(ResolvedEntry::Array(resolved_array)) + } + Entry::Null => Ok(ResolvedEntry::Null), + Entry::Input(input) => Self::resolve_input(input, inputs), + } + } + + fn insert_at_path<'input>( + obj: &mut IndexMap<&'input str, ResolvedEntry<'input>>, + path: &[&'input str], + value: ResolvedEntry<'input>, + ) -> Result<(), Error> { + if path.is_empty() { + return Err(Error::DeserializationError("Empty path".to_string())); + } + + if path.len() == 1 { + obj.insert(path[0], value); + return Ok(()); + } + + let (first, rest) = path.split_first().unwrap(); + let entry = obj + .entry(first) + .or_insert_with(|| ResolvedEntry::Object(indexmap::IndexMap::new())); + + match entry { + ResolvedEntry::Object(nested_obj) => { + Self::insert_at_path(nested_obj, rest, value)?; + } + _ => { + return Err(Error::DeserializationError(format!( + "Cannot index into non-object at key: {}", + first + ))); + } + } + + Ok(()) + } + + fn resolve_input<'input>( + input: &str, + inputs: &Inputs<'input>, + ) -> Result> { + if let Some(env) = input.strip_prefix("$env_") { + if let Ok(env) = std::env::var(env) { + return Ok(ResolvedEntry::String(Cow::Owned(env))); + } + } + + if let Some(entry) = inputs.get(input) { + return Self::resolve_entry(entry, inputs); + } + + panic!("No input found") // FIXME: return an error } } + pub fn from_str<'a, T>(s: &'a str) -> Result where T: de::Deserialize<'a>, @@ -29,225 +184,110 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { where V: de::Visitor<'de>, { - todo!() - } - - fn deserialize_bool(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_i8(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_i16(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_i32(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_i64(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_u8(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_u16(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_u32(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_u64(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_f32(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_f64(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_char(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_str(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() + match self.entry { + ResolvedEntry::String(ref string) => visitor.visit_str(string), + ResolvedEntry::Integer(integer) => match integer.inner { + IntegerType::Negative(n) => visitor.visit_i64(n), + IntegerType::Positive(n) => visitor.visit_u64(n), + }, + ResolvedEntry::Float(float) => visitor.visit_f64(float), + ResolvedEntry::Boolean(boolean) => visitor.visit_bool(boolean), + ResolvedEntry::Null => visitor.visit_unit(), + ResolvedEntry::Array(ref mut items) => { + let mut seq = Vec::new(); + std::mem::swap(items, &mut seq); + + visitor.visit_seq(SeqAccess::new(seq)) + } + ResolvedEntry::Object(ref mut object) => { + let mut map = IndexMap::new(); + std::mem::swap(object, &mut map); + + visitor.visit_map(MapAccess::new(map)) + } + } } - fn deserialize_string(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_bytes(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_byte_buf(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_option(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_unit(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } - - fn deserialize_unit_struct( - self, - name: &'static str, - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - todo!() + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any } +} - fn deserialize_newtype_struct( - self, - name: &'static str, - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } +struct SeqAccess<'de> { + items: std::vec::IntoIter>, +} - fn deserialize_seq(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() +impl<'de> SeqAccess<'de> { + pub fn new(items: Vec>) -> Self { + Self { + items: items.into_iter(), + } } +} - fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } +impl<'de> de::SeqAccess<'de> for SeqAccess<'de> { + type Error = Error; - fn deserialize_tuple_struct( - self, - name: &'static str, - len: usize, - visitor: V, - ) -> Result + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> where - V: de::Visitor<'de>, + T: de::DeserializeSeed<'de>, { - todo!() + match self.items.next() { + Some(item) => { + let mut deserializer = Deserializer::with_entry(item); + seed.deserialize(&mut deserializer).map(Some) + } + None => Ok(None), + } } +} - fn deserialize_map(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } +struct MapAccess<'de> { + items: indexmap::map::IntoIter<&'de str, ResolvedEntry<'de>>, + current_value: Option>, +} - fn deserialize_struct( - self, - name: &'static str, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - todo!() +impl<'de> MapAccess<'de> { + fn new(items: IndexMap<&'de str, ResolvedEntry<'de>>) -> Self { + Self { + items: items.into_iter(), + current_value: None, + } } +} - fn deserialize_enum( - self, - name: &'static str, - variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - todo!() - } +impl<'de> de::MapAccess<'de> for MapAccess<'de> { + type Error = Error; - fn deserialize_identifier(self, visitor: V) -> Result + fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> where - V: de::Visitor<'de>, + K: de::DeserializeSeed<'de>, { - todo!() + match self.items.next() { + Some((key, value)) => { + self.current_value = Some(value); + let mut key_deserializer = + Deserializer::with_entry(ResolvedEntry::String(Cow::Borrowed(key))); + seed.deserialize(&mut key_deserializer).map(Some) + } + None => Ok(None), + } } - fn deserialize_ignored_any(self, visitor: V) -> Result + fn next_value_seed(&mut self, seed: V) -> Result where - V: de::Visitor<'de>, + V: de::DeserializeSeed<'de>, { - todo!() + match self.current_value.take() { + Some(value) => { + let mut deserializer = Deserializer::with_entry(value); + seed.deserialize(&mut deserializer) + } + None => Err(Error::DeserializationError( + "No value available".to_string(), + )), + } } } diff --git a/src/lib.rs b/src/lib.rs index b001dbb..4e5c43e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,7 @@ mod de; mod lua; mod error; -mod value; +pub(crate) mod value; pub mod ast; pub mod lexer; diff --git a/src/value/integer.rs b/src/value/integer.rs index e71be42..9d8c206 100644 --- a/src/value/integer.rs +++ b/src/value/integer.rs @@ -1,10 +1,10 @@ use serde::Serialize; use std::fmt::{Debug, Display}; -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] #[repr(transparent)] pub struct Integer { - inner: IntegerType, + pub(crate) inner: IntegerType, } impl Debug for Integer { @@ -22,8 +22,8 @@ impl Display for Integer { } } -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)] -enum IntegerType { +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone,Copy)] +pub(crate) enum IntegerType { Negative(i64), Positive(u64), } diff --git a/src/value/mod.rs b/src/value/mod.rs index 27e9448..2f376d4 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -5,6 +5,7 @@ mod integer; mod ser; pub use integer::Integer; +pub(crate) use integer::IntegerType; /// Object: Key-value collection that preserves insertion order pub type Object = IndexMap; From 2ab9346b292e08f3282efbdd33e3ab859cce4ad4 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 17 Jun 2025 23:22:55 +0200 Subject: [PATCH 14/68] Update generate toml and yml examples --- assets/outputs/toml/complex_keys.toml | 2 +- assets/outputs/yaml/complex_keys.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/outputs/toml/complex_keys.toml b/assets/outputs/toml/complex_keys.toml index 072b05e..d550ef7 100644 --- a/assets/outputs/toml/complex_keys.toml +++ b/assets/outputs/toml/complex_keys.toml @@ -1,7 +1,7 @@ with_underscore = 0 with-dash = 1 "with_🌽" = 2 -'!"£$%^&*()_' = 3 +'!£$%^&*()_' = 3 j12345 = 4 [foo] diff --git a/assets/outputs/yaml/complex_keys.yml b/assets/outputs/yaml/complex_keys.yml index cb4e419..24d3214 100644 --- a/assets/outputs/yaml/complex_keys.yml +++ b/assets/outputs/yaml/complex_keys.yml @@ -1,7 +1,7 @@ with_underscore: 0 with-dash: 1 with_🌽: 2 -'!"£$%^&*()_': 3 +'!£$%^&*()_': 3 j12345: 4 foo: bar-baz: hello From 3d35b48719bf022bea0038dacd8888d66d2452c4 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 17 Jun 2025 23:37:14 +0200 Subject: [PATCH 15/68] Rename ResolvedEntry to BorrowedValue and make it public --- src/de.rs | 110 +++++++++++++++++++++++++++++++++++------------------ src/lib.rs | 2 +- 2 files changed, 75 insertions(+), 37 deletions(-) diff --git a/src/de.rs b/src/de.rs index af7e023..61cdbcb 100644 --- a/src/de.rs +++ b/src/de.rs @@ -8,27 +8,65 @@ use crate::{ lexer::Lexer, parser::RootParser, value::IntegerType, - Error, Integer, Result, + Error, Integer, Result, Value, }; #[derive(Clone)] pub struct Deserializer<'de> { - entry: ResolvedEntry<'de>, + entry: BorrowedValue<'de>, } #[derive(Clone)] -enum ResolvedEntry<'input> { +pub enum BorrowedValue<'input> { String(Cow<'input, str>), Integer(Integer), Float(f64), Boolean(bool), Null, - Array(Vec>), - Object(IndexMap<&'input str, ResolvedEntry<'input>>), + Array(Vec>), + Object(IndexMap<&'input str, BorrowedValue<'input>>), +} + +impl BorrowedValue<'_> { + pub fn into_value(self) -> Value { + match self { + BorrowedValue::String(string) => Value::String(string.into_owned()), + BorrowedValue::Integer(integer) => Value::Integer(integer), + BorrowedValue::Float(float) => Value::Float(float), + BorrowedValue::Boolean(boolean) => Value::Boolean(boolean), + BorrowedValue::Null => Value::Null, + BorrowedValue::Array(array) => { + Value::Array(array.into_iter().map(Value::from).collect()) + } + BorrowedValue::Object(object) => Value::Object( + object + .into_iter() + .map(|(k, v)| (k.to_owned(), Value::from(v))) + .collect(), + ), + } + } +} + +impl From> for Value { + fn from(entry: BorrowedValue<'_>) -> Self { + entry.into_value() + } +} + +pub fn parse(input: &str) -> Result { + Deserializer::parse(input) } impl<'de> Deserializer<'de> { - /// Refer to the `Deserializer::from_str` method for more info. + pub fn parse(input: &str) -> Result { + let mut lexer = Lexer::new(input); + let parser = RootParser::new(); + let Root { inputs, object } = parser.parse(input, &mut lexer).expect("Failed to parse"); // FIXME: handler errors + + Self::resolve_entry(&Entry::Object(object), &inputs) + } + pub fn from_str(input: &'de str) -> Result { let mut lexer = Lexer::new(input); let parser = RootParser::new(); @@ -39,19 +77,19 @@ impl<'de> Deserializer<'de> { }) } - fn with_entry(entry: ResolvedEntry<'de>) -> Self { + fn with_entry(entry: BorrowedValue<'de>) -> Self { Self { entry } } fn resolve_entry<'input>( entry: &Entry<'input>, inputs: &Inputs<'input>, - ) -> Result> { + ) -> Result> { match entry { - Entry::String(s) => Ok(ResolvedEntry::String(Cow::Borrowed(s))), // TODO: handle interpolation here or at lexer level? - Entry::Integer(integer) => Ok(ResolvedEntry::Integer(*integer)), - Entry::Float(float) => Ok(ResolvedEntry::Float(*float)), - Entry::Boolean(boolean) => Ok(ResolvedEntry::Boolean(*boolean)), + Entry::String(s) => Ok(BorrowedValue::String(Cow::Borrowed(s))), // TODO: handle interpolation here or at lexer level? + Entry::Integer(integer) => Ok(BorrowedValue::Integer(*integer)), + Entry::Float(float) => Ok(BorrowedValue::Float(*float)), + Entry::Boolean(boolean) => Ok(BorrowedValue::Boolean(*boolean)), Entry::Object(obj) => { let mut resolved_object = IndexMap::new(); @@ -67,7 +105,7 @@ impl<'de> Deserializer<'de> { PairOrSpread::Spread(name) => { if let Some(spread_entry) = inputs.get(name) { match Self::resolve_entry(spread_entry, inputs)? { - ResolvedEntry::Object(spread_obj) => { + BorrowedValue::Object(spread_obj) => { for (k, v) in spread_obj { resolved_object.insert(k, v); } @@ -89,7 +127,7 @@ impl<'de> Deserializer<'de> { } } - Ok(ResolvedEntry::Object(resolved_object)) + Ok(BorrowedValue::Object(resolved_object)) } Entry::Array(items) => { let mut resolved_array = Vec::with_capacity(items.len()); // We need at least the same amount of items @@ -101,7 +139,7 @@ impl<'de> Deserializer<'de> { } EntryOrSpread::Spread(spread) => match Self::resolve_input(spread, inputs)? { - ResolvedEntry::Array(array) => { + BorrowedValue::Array(array) => { resolved_array.extend(array); } _ => panic!("Only arrays support being spreaded"), // FIXME: return an error @@ -109,17 +147,17 @@ impl<'de> Deserializer<'de> { } } - Ok(ResolvedEntry::Array(resolved_array)) + Ok(BorrowedValue::Array(resolved_array)) } - Entry::Null => Ok(ResolvedEntry::Null), + Entry::Null => Ok(BorrowedValue::Null), Entry::Input(input) => Self::resolve_input(input, inputs), } } fn insert_at_path<'input>( - obj: &mut IndexMap<&'input str, ResolvedEntry<'input>>, + obj: &mut IndexMap<&'input str, BorrowedValue<'input>>, path: &[&'input str], - value: ResolvedEntry<'input>, + value: BorrowedValue<'input>, ) -> Result<(), Error> { if path.is_empty() { return Err(Error::DeserializationError("Empty path".to_string())); @@ -133,10 +171,10 @@ impl<'de> Deserializer<'de> { let (first, rest) = path.split_first().unwrap(); let entry = obj .entry(first) - .or_insert_with(|| ResolvedEntry::Object(indexmap::IndexMap::new())); + .or_insert_with(|| BorrowedValue::Object(indexmap::IndexMap::new())); match entry { - ResolvedEntry::Object(nested_obj) => { + BorrowedValue::Object(nested_obj) => { Self::insert_at_path(nested_obj, rest, value)?; } _ => { @@ -153,10 +191,10 @@ impl<'de> Deserializer<'de> { fn resolve_input<'input>( input: &str, inputs: &Inputs<'input>, - ) -> Result> { + ) -> Result> { if let Some(env) = input.strip_prefix("$env_") { if let Ok(env) = std::env::var(env) { - return Ok(ResolvedEntry::String(Cow::Owned(env))); + return Ok(BorrowedValue::String(Cow::Owned(env))); } } @@ -185,21 +223,21 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { V: de::Visitor<'de>, { match self.entry { - ResolvedEntry::String(ref string) => visitor.visit_str(string), - ResolvedEntry::Integer(integer) => match integer.inner { + BorrowedValue::String(ref string) => visitor.visit_str(string), + BorrowedValue::Integer(integer) => match integer.inner { IntegerType::Negative(n) => visitor.visit_i64(n), IntegerType::Positive(n) => visitor.visit_u64(n), }, - ResolvedEntry::Float(float) => visitor.visit_f64(float), - ResolvedEntry::Boolean(boolean) => visitor.visit_bool(boolean), - ResolvedEntry::Null => visitor.visit_unit(), - ResolvedEntry::Array(ref mut items) => { + BorrowedValue::Float(float) => visitor.visit_f64(float), + BorrowedValue::Boolean(boolean) => visitor.visit_bool(boolean), + BorrowedValue::Null => visitor.visit_unit(), + BorrowedValue::Array(ref mut items) => { let mut seq = Vec::new(); std::mem::swap(items, &mut seq); visitor.visit_seq(SeqAccess::new(seq)) } - ResolvedEntry::Object(ref mut object) => { + BorrowedValue::Object(ref mut object) => { let mut map = IndexMap::new(); std::mem::swap(object, &mut map); @@ -216,11 +254,11 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { } struct SeqAccess<'de> { - items: std::vec::IntoIter>, + items: std::vec::IntoIter>, } impl<'de> SeqAccess<'de> { - pub fn new(items: Vec>) -> Self { + pub fn new(items: Vec>) -> Self { Self { items: items.into_iter(), } @@ -245,12 +283,12 @@ impl<'de> de::SeqAccess<'de> for SeqAccess<'de> { } struct MapAccess<'de> { - items: indexmap::map::IntoIter<&'de str, ResolvedEntry<'de>>, - current_value: Option>, + items: indexmap::map::IntoIter<&'de str, BorrowedValue<'de>>, + current_value: Option>, } impl<'de> MapAccess<'de> { - fn new(items: IndexMap<&'de str, ResolvedEntry<'de>>) -> Self { + fn new(items: IndexMap<&'de str, BorrowedValue<'de>>) -> Self { Self { items: items.into_iter(), current_value: None, @@ -269,7 +307,7 @@ impl<'de> de::MapAccess<'de> for MapAccess<'de> { Some((key, value)) => { self.current_value = Some(value); let mut key_deserializer = - Deserializer::with_entry(ResolvedEntry::String(Cow::Borrowed(key))); + Deserializer::with_entry(BorrowedValue::String(Cow::Borrowed(key))); seed.deserialize(&mut key_deserializer).map(Some) } None => Ok(None), diff --git a/src/lib.rs b/src/lib.rs index 4e5c43e..730cac6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,6 @@ pub mod ast; pub mod lexer; lalrpop_util::lalrpop_mod!(pub parser, "/corn.rs"); -pub use de::{from_str, Deserializer}; +pub use de::{from_str, parse, BorrowedValue, Deserializer}; pub use error::{Error, Result}; pub use value::{Integer, Object, Value}; From 73f664df4a169bf40c2d24b1bf04c1d5e5827e85 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 17 Jun 2025 23:45:32 +0200 Subject: [PATCH 16/68] Remove unnecessary extern in parser tests --- tests/parser_tests.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/parser_tests.rs b/tests/parser_tests.rs index 7b6d8ff..ff97e62 100644 --- a/tests/parser_tests.rs +++ b/tests/parser_tests.rs @@ -1,5 +1,3 @@ -extern crate core; - use corn::parse; use paste::paste; use std::fs; From 268d78aa375e92cd10abfb7fab7d1ecc08979dc2 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 17 Jun 2025 23:46:25 +0200 Subject: [PATCH 17/68] Move BorrowedValue to value module --- src/de.rs | 40 +--------------------------------------- src/lib.rs | 4 ++-- src/value/integer.rs | 4 ++-- src/value/mod.rs | 40 ++++++++++++++++++++++++++++++++++++++++ src/value/ser.rs | 29 ++++++++++++++++++++++++++++- 5 files changed, 73 insertions(+), 44 deletions(-) diff --git a/src/de.rs b/src/de.rs index 61cdbcb..db7a40e 100644 --- a/src/de.rs +++ b/src/de.rs @@ -8,7 +8,7 @@ use crate::{ lexer::Lexer, parser::RootParser, value::IntegerType, - Error, Integer, Result, Value, + BorrowedValue, Error, Result, }; #[derive(Clone)] @@ -16,44 +16,6 @@ pub struct Deserializer<'de> { entry: BorrowedValue<'de>, } -#[derive(Clone)] -pub enum BorrowedValue<'input> { - String(Cow<'input, str>), - Integer(Integer), - Float(f64), - Boolean(bool), - Null, - Array(Vec>), - Object(IndexMap<&'input str, BorrowedValue<'input>>), -} - -impl BorrowedValue<'_> { - pub fn into_value(self) -> Value { - match self { - BorrowedValue::String(string) => Value::String(string.into_owned()), - BorrowedValue::Integer(integer) => Value::Integer(integer), - BorrowedValue::Float(float) => Value::Float(float), - BorrowedValue::Boolean(boolean) => Value::Boolean(boolean), - BorrowedValue::Null => Value::Null, - BorrowedValue::Array(array) => { - Value::Array(array.into_iter().map(Value::from).collect()) - } - BorrowedValue::Object(object) => Value::Object( - object - .into_iter() - .map(|(k, v)| (k.to_owned(), Value::from(v))) - .collect(), - ), - } - } -} - -impl From> for Value { - fn from(entry: BorrowedValue<'_>) -> Self { - entry.into_value() - } -} - pub fn parse(input: &str) -> Result { Deserializer::parse(input) } diff --git a/src/lib.rs b/src/lib.rs index 730cac6..eb16b7d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,6 @@ pub mod ast; pub mod lexer; lalrpop_util::lalrpop_mod!(pub parser, "/corn.rs"); -pub use de::{from_str, parse, BorrowedValue, Deserializer}; +pub use de::{from_str, parse, Deserializer}; pub use error::{Error, Result}; -pub use value::{Integer, Object, Value}; +pub use value::{BorrowedValue, Integer, Object, Value}; diff --git a/src/value/integer.rs b/src/value/integer.rs index 9d8c206..78d40dc 100644 --- a/src/value/integer.rs +++ b/src/value/integer.rs @@ -4,7 +4,7 @@ use std::fmt::{Debug, Display}; #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] #[repr(transparent)] pub struct Integer { - pub(crate) inner: IntegerType, + pub(crate) inner: IntegerType, } impl Debug for Integer { @@ -22,7 +22,7 @@ impl Display for Integer { } } -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone,Copy)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] pub(crate) enum IntegerType { Negative(i64), Positive(u64), diff --git a/src/value/mod.rs b/src/value/mod.rs index 2f376d4..8a263c7 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use indexmap::IndexMap; mod de; @@ -38,6 +40,44 @@ pub enum Value { Null, } +#[derive(Clone)] +pub enum BorrowedValue<'input> { + String(Cow<'input, str>), + Integer(Integer), + Float(f64), + Boolean(bool), + Null, + Array(Vec>), + Object(IndexMap<&'input str, BorrowedValue<'input>>), +} + +impl BorrowedValue<'_> { + pub fn into_value(self) -> Value { + match self { + BorrowedValue::String(string) => Value::String(string.into_owned()), + BorrowedValue::Integer(integer) => Value::Integer(integer), + BorrowedValue::Float(float) => Value::Float(float), + BorrowedValue::Boolean(boolean) => Value::Boolean(boolean), + BorrowedValue::Null => Value::Null, + BorrowedValue::Array(array) => { + Value::Array(array.into_iter().map(Value::from).collect()) + } + BorrowedValue::Object(object) => Value::Object( + object + .into_iter() + .map(|(k, v)| (k.to_owned(), Value::from(v))) + .collect(), + ), + } + } +} + +impl From> for Value { + fn from(entry: BorrowedValue<'_>) -> Self { + entry.into_value() + } +} + impl Value { /// Returns true if the value is a String. pub const fn is_string(&self) -> bool { diff --git a/src/value/ser.rs b/src/value/ser.rs index 65abb5b..c44e50d 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -1,6 +1,6 @@ use serde::Serialize; -use crate::Value; +use crate::{BorrowedValue, Value}; impl Serialize for Value { #[inline] @@ -28,3 +28,30 @@ impl Serialize for Value { } } } + +impl Serialize for BorrowedValue<'_> { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match self { + Self::String(s) => serializer.serialize_str(s), + Self::Integer(i) => i.serialize(serializer), + Self::Float(f) => f.serialize(serializer), + Self::Boolean(v) => serializer.serialize_bool(*v), + Self::Object(obj) => { + use serde::ser::SerializeMap; + let mut map = serializer.serialize_map(Some(obj.len()))?; + + for (k, v) in obj { + map.serialize_entry(k, v)?; + } + + map.end() + } + Self::Array(v) => v.serialize(serializer), + Self::Null => serializer.serialize_unit(), + } + } +} From a81457bafc19cbb46aeeb92bbc7cfb88c2be9509 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Wed, 18 Jun 2025 02:32:36 +0200 Subject: [PATCH 18/68] Implement string interpolation and unicode escaping --- src/ast.rs | 4 +- src/corn.lalrpop | 4 +- src/de.rs | 26 +++++++++- src/lexer.rs | 124 ++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 141 insertions(+), 17 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 00f70eb..9f51a52 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use crate::Integer; +use crate::{lexer::StringPart, Integer}; /// Store for input declarations pub type Inputs<'input> = HashMap<&'input str, Entry<'input>>; @@ -41,7 +41,7 @@ pub struct ChainedKey<'input> { #[derive(Debug, Clone)] pub enum Entry<'input> { /// String literal - String(&'input str), + String(Vec>), /// Integer value Integer(Integer), /// Float value diff --git a/src/corn.lalrpop b/src/corn.lalrpop index c247c10..d441637 100644 --- a/src/corn.lalrpop +++ b/src/corn.lalrpop @@ -1,5 +1,5 @@ use crate::ast::{Root, Entry, Object, Inputs, PairOrSpread, ChainedKey, EntryOrSpread}; -use crate::lexer::{LexicalError, Token}; +use crate::lexer::{LexicalError, Token, StringPart}; use crate::Integer; grammar<'input>(input: &'input str); @@ -19,7 +19,7 @@ extern { "]" => Token::CloseBracket, "." => Token::Chain, ".." => Token::Spread, - "literal" => Token::StringLiteral(<&'input str>), + "literal" => Token::Literal(>>), "int" => Token::Integer(), "float" => Token::Float(), "bool" => Token::Boolean(), diff --git a/src/de.rs b/src/de.rs index db7a40e..c0e12e9 100644 --- a/src/de.rs +++ b/src/de.rs @@ -5,7 +5,7 @@ use serde::{de, forward_to_deserialize_any}; use crate::{ ast::{Entry, EntryOrSpread, Inputs, PairOrSpread, Root}, - lexer::Lexer, + lexer::{Lexer, StringPart}, parser::RootParser, value::IntegerType, BorrowedValue, Error, Result, @@ -48,7 +48,29 @@ impl<'de> Deserializer<'de> { inputs: &Inputs<'input>, ) -> Result> { match entry { - Entry::String(s) => Ok(BorrowedValue::String(Cow::Borrowed(s))), // TODO: handle interpolation here or at lexer level? + Entry::String(parts) => { + if parts.is_empty() { + return Ok(BorrowedValue::String(Cow::Borrowed(""))); + } + + let mut base = String::new(); + + for part in parts { + match part { + StringPart::Literal(lit) => base.push_str(lit), + StringPart::Input(input) => { + let input = Self::resolve_input(input, inputs)?; + + match input { + BorrowedValue::String(string) => base.push_str(&string), + _ => panic!("Only strings can be interpolated into string"), // FIXME: Custom error + } + } + } + } + + Ok(BorrowedValue::String(Cow::Owned(base))) + } Entry::Integer(integer) => Ok(BorrowedValue::Integer(*integer)), Entry::Float(float) => Ok(BorrowedValue::Float(*float)), Entry::Boolean(boolean) => Ok(BorrowedValue::Boolean(*boolean)), diff --git a/src/lexer.rs b/src/lexer.rs index 2fbe545..5d2cf9e 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -1,4 +1,5 @@ use std::{ + borrow::Cow, fmt, num::{ParseFloatError, ParseIntError}, }; @@ -93,22 +94,124 @@ pub enum Token<'input> { #[regex(r"-?[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?", |lex| lex.slice().parse::())] Float(f64), - #[regex(r"\$[a-zA-Z_][a-zA-Z0-9_]*", |lex| lex.slice())] + #[regex(r"\$[a-zA-Z_][a-zA-Z0-9_]*", |lex| lex.slice().trim_start_matches('$'))] InputName(&'input str), - #[regex(r#""(?:[^"\\]|\\[\\\"nrt$]|\\u[0-9a-fA-F]{4})*""#, |lex| lex.slice().trim_matches('"'))] - StringLiteral(&'input str), - - InterpolatedString(Vec), // FIXME: parse interpolated strings + #[token("\"", parse_literal)] + Literal(Vec>), #[regex(r#"'(?:[^'\\]|\\.)*'|[^\s.=0-9\[\]{}"'][^\s.=\[\]{}"']*"#, |lex| lex.slice().trim_matches('\''))] Key(&'input str), } +#[derive(Logos, Debug, PartialEq, Clone)] +enum StringContext<'input> { + #[token("\"")] + Quote, + #[regex(r#"[^\"$\\{]+"#)] + Content, + + #[token("\\n")] + NewlineEscape, + #[token("\\r")] + CarriageReturnEscape, + #[token("\\t")] + TabEscape, + #[token("\\\\")] + BackslashEscape, + #[token("\\\"")] + QuoteEscape, + #[token("\\$")] + DollarEscape, + #[token("\\{")] + OpenBraceEscape, + #[token("\\}")] + CloseBraceEscape, + #[regex(r"\\u[0-9a-fA-F]{4}")] + UnicodeEscape, + + #[regex(r"\$\{[a-zA-Z_][a-zA-Z0-9_]*\}", |lex| lex.slice())] + Interpolation(&'input str), +} + #[derive(Debug, Clone, PartialEq)] -pub enum StringPart { - Literal(String), - Input(String), +pub enum StringPart<'input> { + Literal(Cow<'input, str>), + Input(&'input str), +} + +fn parse_literal<'input>( + lex: &mut logos::Lexer<'input, Token<'input>>, +) -> Option>> { + let mut string_lex = lex.clone().morph::(); + + let mut parts = Vec::new(); + let mut current_literal = String::new(); + + while let Some(Ok(token)) = string_lex.next() { + match token { + StringContext::Quote => break, + StringContext::Content => current_literal.push_str(string_lex.slice()), + StringContext::Interpolation(input) => { + if !current_literal.is_empty() { + parts.push(StringPart::Literal(Cow::Owned(std::mem::take( + &mut current_literal, + )))); + } + + parts.push(StringPart::Input( + input.trim_start_matches("${").trim_end_matches('}'), + )) + } + StringContext::NewlineEscape => { + current_literal.push('\n'); + } + StringContext::CarriageReturnEscape => { + current_literal.push('\r'); + } + StringContext::TabEscape => { + current_literal.push('\t'); + } + StringContext::BackslashEscape => { + current_literal.push('\\'); + } + StringContext::QuoteEscape => { + current_literal.push('"'); + } + StringContext::DollarEscape => { + current_literal.push('$'); + } + StringContext::OpenBraceEscape => { + current_literal.push('{'); + } + StringContext::CloseBraceEscape => { + current_literal.push('}'); + } + StringContext::UnicodeEscape => { + let slice = string_lex.slice(); + let hex_part = &slice[2..]; // Skip "\\u" + + if let Ok(code) = u32::from_str_radix(hex_part, 16) { + if let Some(unicode_char) = char::from_u32(code) { + current_literal.push(unicode_char); + continue; + } + } + + current_literal.push('\u{FFFD}'); + } + } + } + + if !current_literal.is_empty() { + parts.push(StringPart::Literal(Cow::Owned(std::mem::take( + &mut current_literal, + )))); + } + + *lex = string_lex.morph(); + + Some(parts) } impl fmt::Display for Token<'_> { @@ -124,12 +227,11 @@ impl fmt::Display for Token<'_> { Self::CloseBracket => write!(f, "]"), Self::Chain => write!(f, "."), Self::Spread => write!(f, ".."), - Self::StringLiteral(lit) => lit.fmt(f), - Self::InterpolatedString(parts) => { + Self::Literal(parts) => { for part in parts { match part { StringPart::Literal(lit) => write!(f, "{lit}")?, - StringPart::Input(input) => write!(f, "${input}")?, + StringPart::Input(input) => write!(f, "{input}")?, } } From ebd7d1f5537b6378cfd548d6c3e804c221c0d781 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Wed, 18 Jun 2025 02:34:46 +0200 Subject: [PATCH 19/68] Remove old parser code --- src/grammar.pest | 93 ----------- src/parser.rs | 425 ----------------------------------------------- 2 files changed, 518 deletions(-) delete mode 100644 src/grammar.pest delete mode 100644 src/parser.rs diff --git a/src/grammar.pest b/src/grammar.pest deleted file mode 100644 index 2cbe2c4..0000000 --- a/src/grammar.pest +++ /dev/null @@ -1,93 +0,0 @@ -WHITESPACE = _{ " " | "\t" | "\r" | "\n" } -COMMENT = _{ "//" ~ (!"\n" ~ ANY)* } - -object = { - "{" - ~ object_value* - ~ "}" -} - -object_value = _{ - pair | spread -} - -spread = { - ".." ~ input -} - -array = { - "[" - ~ array_value* - ~ "]" -} - -array_value = _{ - value | spread -} - -pair = { path ~ "=" ~ value } - -path = ${ - path_seg - ~ ( "." ~ path_seg )* -} - -path_seg = _{ - quoted_path_seg | regular_path_seg -} - -quoted_path_seg = ${ "'" ~ quoted_path_val ~ "'" } -quoted_path_val = ${ quoted_path_char + } -quoted_path_char = _{ - !("'" | "\\") ~ ANY - | "\\" ~ "'" -} - -regular_path_seg = ${ path_char + } - -path_char = _{ !( WHITESPACE | "=" | "." ) ~ ANY } - -value = _{ object | array | input | string | float | integer | boolean | null } - -boolean = { "true" | "false" } -null = { "null" } - -string = ${ - "\"" ~ string_val ~ "\"" -} - -string_val = ${ (input | char)* } - -char = { - !("\"" | "\\") ~ ANY - | "\\" ~ ("\"" | "\\" | "n" | "r" | "t" | "$") - | "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4}) -} - -integer = ${ - hex_integer | decimal_integer -} - -decimal_integer = @{ - "-"? - ~ ("0" | ASCII_NONZERO_DIGIT ~ ("_"? ~ ASCII_DIGIT)*) -} - -hex_integer = @{ - "0x" ~ ASCII_HEX_DIGIT+ -} - -float = @{ - "-"? - ~ ("0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) - ~ ("." ~ ASCII_DIGIT*) - ~ (^"e" ~ ("+" | "-")? ~ ASCII_DIGIT+)? -} - -input = ${ !"\\" ~ "$" ~ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")+ } - -assignment = { input ~ "=" ~ value } - -assign_block = { "let" ~ "{" ~ assignment* ~ "}" ~ "in" } - -config = _{ SOI ~ assign_block? ~ object ~ EOI } diff --git a/src/parser.rs b/src/parser.rs deleted file mode 100644 index 248743f..0000000 --- a/src/parser.rs +++ /dev/null @@ -1,425 +0,0 @@ -use indexmap::IndexMap; -use std::borrow::Cow; -use std::collections::HashMap; -use std::env::var; -use std::fmt::Formatter; - -use pest::iterators::Pair; -use pest::Parser; - -use crate::error::{Error, Result}; -use crate::{Inputs, Object, Value}; - -#[derive(pest_derive::Parser)] -#[grammar = "grammar.pest"] -pub struct AstParser; - -impl std::fmt::Display for Rule { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{self:?}") - } -} - -struct CornParser<'a> { - input_block: Option>, - inputs: Inputs<'a>, -} - -impl<'a> CornParser<'a> { - pub fn new(input_block: Option>) -> Self { - let inputs = HashMap::new(); - Self { - input_block, - inputs, - } - } - - pub fn parse(mut self, object_block: Pair<'a, Rule>) -> Result> { - if let Some(input_block) = self.input_block.take() { - self.parse_assign_block(input_block)?; - } - - let value_block = self.parse_object(object_block)?; - Ok(Value::Object(value_block)) - } - - /// Parses a pair of tokens (marked as a `Rule`) into a `Value`. - fn parse_value(&self, pair: Pair<'a, Rule>) -> Result> { - match pair.as_rule() { - Rule::object => Ok(Value::Object(self.parse_object(pair)?)), - Rule::array => Ok(Value::Array(self.parse_array(pair)?)), - Rule::string => Ok(Value::String(self.parse_string(pair)?)), - Rule::integer => Ok(Value::Integer(Self::parse_integer(pair))), - Rule::float => Ok(Value::Float(Self::parse_float(&pair))), - Rule::boolean => Ok(Value::Boolean(Self::parse_bool(&pair))), - Rule::null => Ok(Value::Null(None)), - Rule::input => { - let key = pair.as_str(); - self.get_input(key) - } - _ => unreachable!(), - } - } - - fn parse_bool(pair: &Pair<'_, Rule>) -> bool { - assert_eq!(pair.as_rule(), Rule::boolean); - match pair.as_str() { - "true" => true, - "false" => false, - _ => unreachable!(), - } - } - - fn parse_integer(pair: Pair<'_, Rule>) -> i64 { - assert_eq!(pair.as_rule(), Rule::integer); - let sub_pair = pair - .into_inner() - .next() - .expect("integers should contain a sub-rule of their type"); - - match sub_pair.as_rule() { - Rule::decimal_integer => sub_pair - .as_str() - .replace('_', "") - .parse() - .expect("decimal integer rules should match valid rust integers"), - Rule::hex_integer => i64::from_str_radix(&sub_pair.as_str()[2..], 16) - .expect("hex integer rules contain valid hex values"), - _ => unreachable!(), - } - } - - fn parse_float(pair: &Pair<'_, Rule>) -> f64 { - assert_eq!(pair.as_rule(), Rule::float); - pair.as_str() - .parse() - .expect("float rules should match valid rust floats") - } - - /// Collects each `char` in a `Rule::string` - /// to form a single `String`. - fn parse_string(&self, pair: Pair<'a, Rule>) -> Result> { - assert_eq!(pair.as_rule(), Rule::string); - - let mut full_string = String::new(); - - let pairs = pair - .into_inner() - .next() - .expect("string rules should contain a valid string value") - .into_inner(); - - for pair in pairs { - match pair.as_rule() { - Rule::char => full_string.push(Self::parse_char(&pair)), - Rule::input => { - let input_name = pair.as_str(); - let value = self.get_input(input_name)?; - match value { - Value::String(value) => full_string.push_str(&value), - _ => return Err(Error::InvalidInterpolationError(input_name.to_string())), - } - } - _ => unreachable!(), - }; - } - - let full_string = if full_string.contains('\n') { - trim_multiline_string(&full_string) - } else { - full_string - }; - - Ok(Cow::Owned(full_string)) - } - - fn parse_char(pair: &Pair<'a, Rule>) -> char { - let str = pair.as_str(); - let mut chars = str.chars(); - - let first_char = chars.next().expect("character to exist"); - if first_char != '\\' { - return first_char; - } - - let second_char = chars.next().expect("character to exist"); - if second_char != 'u' { - return match second_char { - 'n' => '\n', - 'r' => '\r', - 't' => '\t', - '"' => '\"', - '$' => '$', - '\\' => '\\', - _ => unreachable!(), - }; - } - - let num = - u32::from_str_radix(&str[3..], 16).expect("valid hex characters to exist after \\u"); - char::from_u32(num).unwrap_or('\u{FFFD}') - } - - /// Parses each rule in a `Rule::array` - /// to form a vector of `Value`s. - fn parse_array(&self, block: Pair<'a, Rule>) -> Result>> { - assert_eq!(block.as_rule(), Rule::array); - - let mut arr = vec![]; - - for pair in block.into_inner() { - match pair.as_rule() { - Rule::spread => { - let input = pair - .into_inner() - .next() - .expect("spread operators should contain an input"); - - let input_name = input.as_str(); - let value = self.parse_value(input)?; - - match value { - Value::Array(other) => arr.extend(other), - _ => return Err(Error::InvalidSpreadError(input_name.to_string())), - } - } - _ => arr.push(self.parse_value(pair)?), - }; - } - - Ok(arr) - } - - /// Parses each key/value pair in a `Rule::object` - /// to form a `IndexMap` of Values. - /// - /// An `IndexMap` is used to ensure keys - /// always output in the same order. - fn parse_object(&self, block: Pair<'a, Rule>) -> Result> { - assert_eq!(block.as_rule(), Rule::object); - - let mut obj = IndexMap::new(); - - for pair in block.into_inner() { - match pair.as_rule() { - Rule::pair => { - let mut path_rules = pair.into_inner(); - - let path = path_rules - .next() - .expect("object pairs should contain a key"); - - let paths = Self::parse_path(path); - - let value = self.parse_value( - path_rules - .next() - .expect("object pairs should contain a value"), - )?; - - obj = Self::add_at_path(obj, &paths, value)?; - } - Rule::spread => { - let input = pair - .into_inner() - .next() - .expect("spread operators should contain an input"); - - let input_name = input.as_str(); - let value = self.parse_value(input)?; - - match value { - Value::Object(other) => obj.extend(other), - _ => return Err(Error::InvalidSpreadError(input_name.to_string())), - } - } - _ => unreachable!(), - } - } - - Ok(obj) - } - - fn parse_path(path: Pair) -> Vec> { - path.into_inner() - .map(|pair| match pair.as_rule() { - Rule::regular_path_seg => Cow::Borrowed(pair.as_str()), - Rule::quoted_path_seg => Cow::Owned( - pair.into_inner() - .next() - .expect("quoted paths should contain an inner value") - .as_str() - .replace('\\', ""), - ), - _ => unreachable!(), - }) - .collect::>() - } - - /// Adds `Value` at the `path` in `obj`. - /// - /// `path` is an array where each entry represents another object key, - /// for example `foo.bar` is represented as `["foo", "bar"]`. - /// - /// Objects are created up to the required depth recursively. - fn add_at_path( - mut obj: Object<'a>, - path: &[Cow<'a, str>], - value: Value<'a>, - ) -> Result> { - let (part, path_rest) = path - .split_first() - .expect("paths should contain at least 1 segment"); - - if path_rest.is_empty() { - obj.insert(part.clone(), value); - return Ok(obj); - } - - let child_obj = obj - .shift_remove(part) - .unwrap_or_else(|| Value::Object(IndexMap::new())); - - match child_obj { - Value::Object(map) => { - obj.insert( - part.clone(), - Value::Object(Self::add_at_path(map, path_rest, value)?), - ); - - Ok(obj) - } - _ => Err(Error::InvalidPathError(path.join("."))), - } - } - - /// Parses the `let { } in` block at the start of files. - /// Each input is inserted into into `self.inputs`. - fn parse_assign_block(&mut self, block: Pair<'a, Rule>) -> Result<()> { - assert_eq!(block.as_rule(), Rule::assign_block); - - for pair in block.into_inner() { - let mut assign_rules = pair.into_inner(); - let name = assign_rules - .next() - .expect("input assignments should have a name") - .as_str(); - - let value = self.parse_value( - assign_rules - .next() - .expect("input assignments should have a value"), - )?; - - self.inputs.insert(name, value); - } - - Ok(()) - } - - /// Attempts to get an input value from the `inputs` map. - /// If the `key` starts with `$env_` the system environment variables will be consulted first. - fn get_input(&self, key: &'a str) -> Result> { - if let Some(env_name) = key.strip_prefix("$env_") { - let var = var(env_name); - - if let Ok(var) = var { - return Ok(Value::String(Cow::Owned(var))); - } - } - - if let Some(value) = self.inputs.get(key) { - Ok(value.clone()) - } else { - Err(Error::InputResolveError(key.to_string())) - } - } -} - -/// Takes a multiline string and trims the maximum amount of -/// whitespace at the start of each line -/// while preserving formatting. -/// -/// Based on code from `indoc` crate: -/// -fn trim_multiline_string(string: &str) -> String { - let ignore_first_line = string.starts_with('\n') || string.starts_with("\r\n"); - - let spaces = string - .lines() - .skip(1) - .map(|line| line.chars().take_while(char::is_ascii_whitespace).count()) - .min() - .unwrap_or_default(); - - let mut result = String::with_capacity(string.len()); - for (i, line) in string.lines().enumerate() { - if i > 1 || (i == 1 && !ignore_first_line) { - result.push('\n'); - } - if i == 0 { - // Do not un-indent anything on same line as opening quote - result.push_str(line); - } else if line.len() > spaces { - // Whitespace-only lines may have fewer than the number of spaces - // being removed - result.push_str(&line[spaces..]); - } - } - result -} - -/// Parses the input string into a `Config` -/// containing the resolved inputs -/// and a map of values representing the top-level object. -/// -/// # Examples -/// -/// ```rust -/// use corn::parse; -/// -/// let corn = "{foo = 42}"; -/// -/// let config = parse(corn).unwrap(); -/// let json = serde_json::to_string(&config).unwrap(); -/// -/// assert_eq!(json, "{\"foo\":42}"); -/// ``` -/// -/// # Errors -/// -/// Will fail if the input contains a syntax error. -/// Will fail if the input contains invalid Corn for another reason, -/// including references to undefined inputs or dot-notation for non-object values. -/// Will fail if the input cannot be deserialized for any reaon. -/// -/// Any of the above will return a specific error type with details. -/// -/// # Panics -/// -/// If the internal AST parser produces a tree in an invalid structure, -/// the function will panic. -/// This indicates a severe error in the library and should never occur. -pub fn parse(file: &str) -> Result { - let rules = AstParser::parse(Rule::config, file); - - match rules { - Ok(mut rules) => { - let first_block = rules.next().expect("should be at least 1 rule"); - - match first_block.as_rule() { - Rule::assign_block => { - let parser = CornParser::new(Some(first_block)); - let object_block = rules.next().expect("should always be an object block"); - parser.parse(object_block) - } - Rule::object => { - let parser = CornParser::new(None); - parser.parse(first_block) - } - _ => unreachable!(), - } - } - Err(error) => Err(Error::ParserError(Box::new(error))), - } -} From b2d4a43df2ff26592adcc461ba262bfb6b882993 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Thu, 19 Jun 2025 01:33:02 +0200 Subject: [PATCH 20/68] Fix string interpolation test --- assets/inputs/string_interpolation.corn | 2 +- assets/outputs/json/string.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/inputs/string_interpolation.corn b/assets/inputs/string_interpolation.corn index 465426e..4b0dd10 100644 --- a/assets/inputs/string_interpolation.corn +++ b/assets/inputs/string_interpolation.corn @@ -2,6 +2,6 @@ let { $greeting = "hello" $subject = "world" } in { - foo = "$greeting, $subject" + foo = "${greeting}, ${subject}" bar = "\$escaped" } diff --git a/assets/outputs/json/string.json b/assets/outputs/json/string.json index 53e6ede..61c3a14 100644 --- a/assets/outputs/json/string.json +++ b/assets/outputs/json/string.json @@ -1,6 +1,6 @@ { "foo": "bar", - "bar": "\"\\\n", + "bar": "\"\\\n\r\t", "baz": "a", "qux": "" } From 498a05a9ed3fd13b2c6ced858160a90213f8c80f Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 22 Jun 2025 20:20:44 +0200 Subject: [PATCH 21/68] Implement Deserialize and Deserializer for Integer --- src/value/integer.rs | 60 +++++++++++++++++++++++++++++++++++++++++--- src/value/mod.rs | 19 +++++++++++++- 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/src/value/integer.rs b/src/value/integer.rs index 78d40dc..005032c 100644 --- a/src/value/integer.rs +++ b/src/value/integer.rs @@ -1,10 +1,15 @@ -use serde::Serialize; -use std::fmt::{Debug, Display}; +use serde::{ + de::{self, Visitor}, + forward_to_deserialize_any, Deserialize, Serialize, +}; +use std::fmt::{self, Debug, Display}; + +use crate::Error; #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] #[repr(transparent)] pub struct Integer { - pub(crate) inner: IntegerType, + inner: IntegerType, } impl Debug for Integer { @@ -23,7 +28,7 @@ impl Display for Integer { } #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] -pub(crate) enum IntegerType { +enum IntegerType { Negative(i64), Positive(u64), } @@ -88,3 +93,50 @@ impl Serialize for Integer { } } } + +impl<'de> Deserialize<'de> for Integer { + fn deserialize(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + struct IntegerVisitor; + + impl<'de> Visitor<'de> for IntegerVisitor { + type Value = Integer; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("an Integer") + } + + fn visit_i64(self, value: i64) -> Result { + Ok(value.into()) + } + + fn visit_u64(self, value: u64) -> Result { + Ok(value.into()) + } + } + + deserializer.deserialize_any(IntegerVisitor) + } +} + +impl<'de> de::Deserializer<'de> for Integer { + type Error = Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.inner { + IntegerType::Negative(integer) => visitor.visit_i64(integer), + IntegerType::Positive(integer) => visitor.visit_u64(integer), + } + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } +} diff --git a/src/value/mod.rs b/src/value/mod.rs index 8a263c7..5c545c1 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -7,7 +7,8 @@ mod integer; mod ser; pub use integer::Integer; -pub(crate) use integer::IntegerType; + +use crate::Error; /// Object: Key-value collection that preserves insertion order pub type Object = IndexMap; @@ -70,6 +71,22 @@ impl BorrowedValue<'_> { ), } } + + pub const fn as_type(&self) -> &'static str { + match self { + Self::String(_) => "String", + Self::Integer(_) => "Integer", + Self::Float(_) => "Float", + Self::Boolean(_) => "Boolean", + Self::Null => "Null", + Self::Array(_) => "Array", + Self::Object(_) => "Object", + } + } + + pub(crate) fn invalid_type(&self, exp: &'static str) -> Error { + Error::DeserializationError(format!("Invalid type: {}, expected {exp}", self.as_type())) + } } impl From> for Value { From 69428ad8c0747dd9894e7afe467a6501ae0de65e Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 22 Jun 2025 20:47:50 +0200 Subject: [PATCH 22/68] Implement the full deserializer instead of forwading --- src/de.rs | 235 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 225 insertions(+), 10 deletions(-) diff --git a/src/de.rs b/src/de.rs index c0e12e9..4a66711 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1,13 +1,12 @@ use std::borrow::Cow; use indexmap::IndexMap; -use serde::{de, forward_to_deserialize_any}; +use serde::de::{self, IntoDeserializer}; use crate::{ ast::{Entry, EntryOrSpread, Inputs, PairOrSpread, Root}, lexer::{Lexer, StringPart}, parser::RootParser, - value::IntegerType, BorrowedValue, Error, Result, }; @@ -199,6 +198,20 @@ where T::deserialize(&mut deserializer) } +macro_rules! deserialize_number { + ($method:ident) => { + fn $method(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.entry { + BorrowedValue::Integer(integer) => integer.deserialize_any(visitor), + ref value => Err(value.invalid_type("Integer")), + } + } + }; +} + impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { type Error = Error; @@ -208,10 +221,7 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { { match self.entry { BorrowedValue::String(ref string) => visitor.visit_str(string), - BorrowedValue::Integer(integer) => match integer.inner { - IntegerType::Negative(n) => visitor.visit_i64(n), - IntegerType::Positive(n) => visitor.visit_u64(n), - }, + BorrowedValue::Integer(integer) => integer.deserialize_any(visitor), BorrowedValue::Float(float) => visitor.visit_f64(float), BorrowedValue::Boolean(boolean) => visitor.visit_bool(boolean), BorrowedValue::Null => visitor.visit_unit(), @@ -230,10 +240,215 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { } } - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - bytes byte_buf option unit unit_struct newtype_struct seq tuple - tuple_struct map struct enum identifier ignored_any + fn deserialize_bool(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.entry { + BorrowedValue::Boolean(boolean) => visitor.visit_bool(boolean), + ref value => Err(value.invalid_type("Boolean")), + } + } + + deserialize_number!(deserialize_i8); + deserialize_number!(deserialize_i16); + deserialize_number!(deserialize_i32); + deserialize_number!(deserialize_i64); + deserialize_number!(deserialize_u8); + deserialize_number!(deserialize_u16); + deserialize_number!(deserialize_u32); + deserialize_number!(deserialize_u64); + + fn deserialize_f32(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_f64(visitor) + } + + fn deserialize_f64(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.entry { + BorrowedValue::Float(float) => visitor.visit_f64(float), + ref value => Err(value.invalid_type("Float")), + } + } + + fn deserialize_char(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_str(visitor) + } + + fn deserialize_str(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.entry { + BorrowedValue::String(ref string) => visitor.visit_str(string), + ref value => Err(value.invalid_type("String")), + } + } + + fn deserialize_string(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_str(visitor) + } + + fn deserialize_bytes(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.entry { + BorrowedValue::String(ref string) => visitor.visit_bytes(string.as_bytes()), + ref value => Err(value.invalid_type("Byte String")), + } + } + + fn deserialize_byte_buf(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_bytes(visitor) + } + + fn deserialize_option(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.entry { + BorrowedValue::Null => visitor.visit_none(), + _ => visitor.visit_some(self), + } + } + + fn deserialize_unit(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.entry { + BorrowedValue::Null => visitor.visit_unit(), + ref value => Err(value.invalid_type("Null")), + } + } + + fn deserialize_unit_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_unit(visitor) + } + + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_seq(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.entry { + BorrowedValue::Array(ref mut items) => { + let mut seq = Vec::new(); + std::mem::swap(items, &mut seq); + + visitor.visit_seq(SeqAccess::new(seq)) + } + ref value => Err(value.invalid_type("Array")), + } + } + + fn deserialize_tuple(self, _len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_map(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.entry { + BorrowedValue::Object(ref mut object) => { + let mut map = IndexMap::new(); + std::mem::swap(object, &mut map); + + visitor.visit_map(MapAccess::new(map)) + } + ref value => Err(value.invalid_type("Object")), + } + } + + fn deserialize_struct( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_map(visitor) + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + match self.entry { + BorrowedValue::String(ref string) => { + visitor.visit_enum(string.as_ref().into_deserializer()) + } + ref value => Err(value.invalid_type("String or Object")), + } + } + + fn deserialize_identifier(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_str(visitor) + } + + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_any(visitor) } } From b704c681ccf31637cb265d48195293f96ad6c6cc Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 22 Jun 2025 20:48:58 +0200 Subject: [PATCH 23/68] Fix env inputs parsing --- src/de.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de.rs b/src/de.rs index 4a66711..b83314c 100644 --- a/src/de.rs +++ b/src/de.rs @@ -175,7 +175,7 @@ impl<'de> Deserializer<'de> { input: &str, inputs: &Inputs<'input>, ) -> Result> { - if let Some(env) = input.strip_prefix("$env_") { + if let Some(env) = input.strip_prefix("env_") { if let Ok(env) = std::env::var(env) { return Ok(BorrowedValue::String(Cow::Owned(env))); } From f7dad5fc8b9f0b2deb26dfcbff00a9976e207f20 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 22 Jun 2025 20:52:58 +0200 Subject: [PATCH 24/68] Rename internal entry to value --- src/de.rs | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/de.rs b/src/de.rs index b83314c..1772812 100644 --- a/src/de.rs +++ b/src/de.rs @@ -12,7 +12,7 @@ use crate::{ #[derive(Clone)] pub struct Deserializer<'de> { - entry: BorrowedValue<'de>, + value: BorrowedValue<'de>, } pub fn parse(input: &str) -> Result { @@ -34,12 +34,12 @@ impl<'de> Deserializer<'de> { let Root { inputs, object } = parser.parse(input, &mut lexer).expect("Failed to parse"); // FIXME: handler errors Ok(Self { - entry: Self::resolve_entry(&Entry::Object(object), &inputs)?, + value: Self::resolve_entry(&Entry::Object(object), &inputs)?, }) } - fn with_entry(entry: BorrowedValue<'de>) -> Self { - Self { entry } + fn with_value(value: BorrowedValue<'de>) -> Self { + Self { value } } fn resolve_entry<'input>( @@ -204,7 +204,7 @@ macro_rules! deserialize_number { where V: de::Visitor<'de>, { - match self.entry { + match self.value { BorrowedValue::Integer(integer) => integer.deserialize_any(visitor), ref value => Err(value.invalid_type("Integer")), } @@ -219,7 +219,7 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { where V: de::Visitor<'de>, { - match self.entry { + match self.value { BorrowedValue::String(ref string) => visitor.visit_str(string), BorrowedValue::Integer(integer) => integer.deserialize_any(visitor), BorrowedValue::Float(float) => visitor.visit_f64(float), @@ -244,7 +244,7 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { where V: de::Visitor<'de>, { - match self.entry { + match self.value { BorrowedValue::Boolean(boolean) => visitor.visit_bool(boolean), ref value => Err(value.invalid_type("Boolean")), } @@ -270,7 +270,7 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { where V: de::Visitor<'de>, { - match self.entry { + match self.value { BorrowedValue::Float(float) => visitor.visit_f64(float), ref value => Err(value.invalid_type("Float")), } @@ -287,7 +287,7 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { where V: de::Visitor<'de>, { - match self.entry { + match self.value { BorrowedValue::String(ref string) => visitor.visit_str(string), ref value => Err(value.invalid_type("String")), } @@ -304,7 +304,7 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { where V: de::Visitor<'de>, { - match self.entry { + match self.value { BorrowedValue::String(ref string) => visitor.visit_bytes(string.as_bytes()), ref value => Err(value.invalid_type("Byte String")), } @@ -321,7 +321,7 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { where V: de::Visitor<'de>, { - match self.entry { + match self.value { BorrowedValue::Null => visitor.visit_none(), _ => visitor.visit_some(self), } @@ -331,7 +331,7 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { where V: de::Visitor<'de>, { - match self.entry { + match self.value { BorrowedValue::Null => visitor.visit_unit(), ref value => Err(value.invalid_type("Null")), } @@ -363,7 +363,7 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { where V: de::Visitor<'de>, { - match self.entry { + match self.value { BorrowedValue::Array(ref mut items) => { let mut seq = Vec::new(); std::mem::swap(items, &mut seq); @@ -397,7 +397,7 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { where V: de::Visitor<'de>, { - match self.entry { + match self.value { BorrowedValue::Object(ref mut object) => { let mut map = IndexMap::new(); std::mem::swap(object, &mut map); @@ -429,7 +429,7 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { where V: de::Visitor<'de>, { - match self.entry { + match self.value { BorrowedValue::String(ref string) => { visitor.visit_enum(string.as_ref().into_deserializer()) } @@ -473,7 +473,7 @@ impl<'de> de::SeqAccess<'de> for SeqAccess<'de> { { match self.items.next() { Some(item) => { - let mut deserializer = Deserializer::with_entry(item); + let mut deserializer = Deserializer::with_value(item); seed.deserialize(&mut deserializer).map(Some) } None => Ok(None), @@ -506,7 +506,7 @@ impl<'de> de::MapAccess<'de> for MapAccess<'de> { Some((key, value)) => { self.current_value = Some(value); let mut key_deserializer = - Deserializer::with_entry(BorrowedValue::String(Cow::Borrowed(key))); + Deserializer::with_value(BorrowedValue::String(Cow::Borrowed(key))); seed.deserialize(&mut key_deserializer).map(Some) } None => Ok(None), @@ -519,7 +519,7 @@ impl<'de> de::MapAccess<'de> for MapAccess<'de> { { match self.current_value.take() { Some(value) => { - let mut deserializer = Deserializer::with_entry(value); + let mut deserializer = Deserializer::with_value(value); seed.deserialize(&mut deserializer) } None => Err(Error::DeserializationError( From 35893eb86c1fff6fab8b8176947e27222d4ab0b4 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 22 Jun 2025 23:08:01 +0200 Subject: [PATCH 25/68] Fully implement enum deserialization --- src/de.rs | 93 +++++++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 2 +- src/value/mod.rs | 3 +- 3 files changed, 95 insertions(+), 3 deletions(-) diff --git a/src/de.rs b/src/de.rs index 1772812..33360ac 100644 --- a/src/de.rs +++ b/src/de.rs @@ -7,7 +7,7 @@ use crate::{ ast::{Entry, EntryOrSpread, Inputs, PairOrSpread, Root}, lexer::{Lexer, StringPart}, parser::RootParser, - BorrowedValue, Error, Result, + BorrowedObject, BorrowedValue, Error, Result, }; #[derive(Clone)] @@ -433,6 +433,12 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { BorrowedValue::String(ref string) => { visitor.visit_enum(string.as_ref().into_deserializer()) } + BorrowedValue::Object(ref mut object) => { + let mut map = IndexMap::new(); + std::mem::swap(object, &mut map); + + visitor.visit_enum(EnumAccess::new(map)) + } ref value => Err(value.invalid_type("String or Object")), } } @@ -528,3 +534,88 @@ impl<'de> de::MapAccess<'de> for MapAccess<'de> { } } } +struct EnumAccess<'de> { + object: BorrowedObject<'de>, +} + +impl<'de> EnumAccess<'de> { + fn new(object: BorrowedObject<'de>) -> Self { + Self { object } + } +} + +impl<'de> de::EnumAccess<'de> for EnumAccess<'de> { + type Error = Error; + type Variant = VariantAccess<'de>; + + fn variant_seed(self, seed: V) -> std::result::Result<(V::Value, Self::Variant), Self::Error> + where + V: de::DeserializeSeed<'de>, + { + if self.object.len() != 1 { + return Err(Error::DeserializationError(format!( + "Expected enum object with exactly one key, found {}", + self.object.len() + ))); + } + + let (key, value) = self.object.into_iter().next().unwrap(); + let mut key_deserializer = + Deserializer::with_value(BorrowedValue::String(Cow::Borrowed(key))); + let variant = seed.deserialize(&mut key_deserializer)?; + + Ok((variant, VariantAccess::new(value))) + } +} + +struct VariantAccess<'de> { + value: BorrowedValue<'de>, +} + +impl<'de> VariantAccess<'de> { + fn new(value: BorrowedValue<'de>) -> Self { + Self { value } + } +} + +impl<'de> de::VariantAccess<'de> for VariantAccess<'de> { + type Error = Error; + + fn unit_variant(self) -> std::result::Result<(), Self::Error> { + match self.value { + BorrowedValue::Null => Ok(()), + ref value => Err(value.invalid_type("unit variant (null)")), + } + } + + fn newtype_variant_seed(self, seed: T) -> std::result::Result + where + T: de::DeserializeSeed<'de>, + { + seed.deserialize(&mut Deserializer::with_value(self.value)) + } + + fn tuple_variant(self, _len: usize, visitor: V) -> std::result::Result + where + V: de::Visitor<'de>, + { + match self.value { + BorrowedValue::Array(items) => visitor.visit_seq(SeqAccess::new(items)), + ref value => Err(value.invalid_type("tuple variant (array)")), + } + } + + fn struct_variant( + self, + _fields: &'static [&'static str], + visitor: V, + ) -> std::result::Result + where + V: de::Visitor<'de>, + { + match self.value { + BorrowedValue::Object(object) => visitor.visit_map(MapAccess::new(object)), + ref value => Err(value.invalid_type("struct variant (object)")), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index eb16b7d..406d59a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,4 +18,4 @@ lalrpop_util::lalrpop_mod!(pub parser, "/corn.rs"); pub use de::{from_str, parse, Deserializer}; pub use error::{Error, Result}; -pub use value::{BorrowedValue, Integer, Object, Value}; +pub use value::{BorrowedObject, BorrowedValue, Integer, Object, Value}; diff --git a/src/value/mod.rs b/src/value/mod.rs index 5c545c1..5dd08d8 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -12,6 +12,7 @@ use crate::Error; /// Object: Key-value collection that preserves insertion order pub type Object = IndexMap; +pub type BorrowedObject<'input> = IndexMap<&'input str, BorrowedValue<'input>>; /// Represents a Corn configuration value. /// @@ -49,7 +50,7 @@ pub enum BorrowedValue<'input> { Boolean(bool), Null, Array(Vec>), - Object(IndexMap<&'input str, BorrowedValue<'input>>), + Object(BorrowedObject<'input>), } impl BorrowedValue<'_> { From b62fdf0b4da1c154310423a61e18bcaefa85955a Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 22 Jun 2025 23:29:46 +0200 Subject: [PATCH 26/68] Allow the cli to compile --- cli/src/error.rs | 12 ++++++------ cli/src/main.rs | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cli/src/error.rs b/cli/src/error.rs index 58f213b..4819aa9 100644 --- a/cli/src/error.rs +++ b/cli/src/error.rs @@ -1,5 +1,5 @@ use colored::Colorize; -use corn::error::Error as CornError; +use corn::Error as CornError; use std::fmt::{Display, Formatter}; use std::io; @@ -21,11 +21,11 @@ impl ExitCode for CornError { fn get_exit_code(&self) -> i32 { match self { CornError::Io(_) => 3, - CornError::ParserError(_) => 1, - CornError::InputResolveError(_) => 2, - CornError::InvalidPathError(_) => 6, - CornError::InvalidSpreadError(_) => 7, - CornError::InvalidInterpolationError(_) => 8, + // CornError::ParserError(_) => 1, + // CornError::InputResolveError(_) => 2, + // CornError::InvalidPathError(_) => 6, + // CornError::InvalidSpreadError(_) => 7, + // CornError::InvalidInterpolationError(_) => 8, CornError::DeserializationError(_) => 5, } } diff --git a/cli/src/main.rs b/cli/src/main.rs index 71e40cb..53cdb5f 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,4 +1,4 @@ -use corn::{parse, Value}; +use corn::{parse, BorrowedValue}; use std::io::Read; use std::process::exit; use std::{fs, io}; @@ -48,7 +48,7 @@ fn main() { let output_type = get_output_type(args.output_type); match parse(&unparsed_file) { - Ok(config) => match serialize(&config, output_type) { + Ok(config) => match serialize(config, output_type) { Ok(serialized) => println!("{serialized}"), Err(err) => handle_err(&err), }, @@ -81,7 +81,7 @@ fn get_output_type(arg: Option) -> OutputType { OutputType::Json } -fn serialize(config: &Value, output_type: OutputType) -> Result { +fn serialize(config: BorrowedValue, output_type: OutputType) -> Result { match output_type { OutputType::Json => serde_json::to_string_pretty(&config).map_err(Error::from), OutputType::Yaml => serde_norway::to_string(&config).map_err(Error::from), From c7a03ab6df1940caca004da56615e4d97500d8df Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 22 Jun 2025 23:41:08 +0200 Subject: [PATCH 27/68] Update string interpolation in complex example --- assets/inputs/complex.corn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/inputs/complex.corn b/assets/inputs/complex.corn index 2d763d5..5710752 100644 --- a/assets/inputs/complex.corn +++ b/assets/inputs/complex.corn @@ -11,7 +11,7 @@ in { // here is another comment name.first = $firstName name.last = $lastName - name.full = "$firstName $lastName" + name.full = "${firstName} ${lastName}" age = $age employment = { From 1bc13cdc81dbe8d5c0ca56e651fe464d151de2d4 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 22 Jun 2025 23:45:11 +0200 Subject: [PATCH 28/68] Fix errors and serialization of null types --- cli/src/error.rs | 8 +++----- src/de.rs | 6 +++--- src/error.rs | 17 ++++++----------- src/value/ser.rs | 4 ++-- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/cli/src/error.rs b/cli/src/error.rs index 4819aa9..4c41a6a 100644 --- a/cli/src/error.rs +++ b/cli/src/error.rs @@ -21,11 +21,9 @@ impl ExitCode for CornError { fn get_exit_code(&self) -> i32 { match self { CornError::Io(_) => 3, - // CornError::ParserError(_) => 1, - // CornError::InputResolveError(_) => 2, - // CornError::InvalidPathError(_) => 6, - // CornError::InvalidSpreadError(_) => 7, - // CornError::InvalidInterpolationError(_) => 8, + CornError::InputResolveError(_) => 2, + CornError::InvalidSpreadError => 7, + CornError::InvalidInterpolationError => 8, CornError::DeserializationError(_) => 5, } } diff --git a/src/de.rs b/src/de.rs index 33360ac..112b80b 100644 --- a/src/de.rs +++ b/src/de.rs @@ -62,7 +62,7 @@ impl<'de> Deserializer<'de> { match input { BorrowedValue::String(string) => base.push_str(&string), - _ => panic!("Only strings can be interpolated into string"), // FIXME: Custom error + _ => return Err(Error::InvalidInterpolationError), } } } @@ -125,7 +125,7 @@ impl<'de> Deserializer<'de> { BorrowedValue::Array(array) => { resolved_array.extend(array); } - _ => panic!("Only arrays support being spreaded"), // FIXME: return an error + _ => return Err(Error::InvalidSpreadError), }, } } @@ -185,7 +185,7 @@ impl<'de> Deserializer<'de> { return Self::resolve_entry(entry, inputs); } - panic!("No input found") // FIXME: return an error + Err(Error::InputResolveError(input.to_string())) } } diff --git a/src/error.rs b/src/error.rs index 24d48de..5ed32bf 100644 --- a/src/error.rs +++ b/src/error.rs @@ -8,20 +8,15 @@ pub enum Error { #[error(transparent)] Io(#[from] std::io::Error), - // #[error(transparent)] - // ParserError(#[from] Box>), + #[error("failed to resolve referenced input `{0}`")] + InputResolveError(String), - // #[error("failed to resolve referenced input `{0}`")] - // InputResolveError(String), + #[error("attempted to spread a type that differs from its containing type")] + InvalidSpreadError, - // #[error("attempted to use dot-notation on non-object value at `{0}`")] - // InvalidPathError(String), + #[error("attempted to interpolate a non-string type into a string")] + InvalidInterpolationError, - // #[error("attempted to spread a type that differs from its containing type at `{0}`")] - // InvalidSpreadError(String), - - // #[error("attempted to interpolate a non-string type into a string at `{0}`")] - // InvalidInterpolationError(String), #[error("failed to deserialize input: {0}")] DeserializationError(String), } diff --git a/src/value/ser.rs b/src/value/ser.rs index c44e50d..aee31cc 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -24,7 +24,7 @@ impl Serialize for Value { map.end() } Self::Array(v) => v.serialize(serializer), - Self::Null => serializer.serialize_unit(), + Self::Null => serializer.serialize_none(), } } } @@ -51,7 +51,7 @@ impl Serialize for BorrowedValue<'_> { map.end() } Self::Array(v) => v.serialize(serializer), - Self::Null => serializer.serialize_unit(), + Self::Null => serializer.serialize_none(), } } } From f16648bab992b3acaea2b674424970a9fa58288c Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 22 Jun 2025 23:55:58 +0200 Subject: [PATCH 29/68] Update the tests generator script --- scripts/generate-tests.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/generate-tests.sh b/scripts/generate-tests.sh index 53cfe96..a63236c 100755 --- a/scripts/generate-tests.sh +++ b/scripts/generate-tests.sh @@ -10,7 +10,7 @@ for file in assets/inputs/*; do echo "$basename" - cargo run --bin corn -- "$file" -t json > assets/outputs/json/"$basename".json - cargo run --bin corn -- "$file" -t yaml > assets/outputs/yaml/"$basename".yml - cargo run --bin corn -- "$file" -t toml > assets/outputs/toml/"$basename".toml + cargo run --package corn-cli -- "$file" -t json > assets/outputs/json/"$basename".json + cargo run --package corn-cli -- "$file" -t yaml > assets/outputs/yaml/"$basename".yml + cargo run --package corn-cli -- "$file" -t toml > assets/outputs/toml/"$basename".toml done \ No newline at end of file From 10712df86d3b3781166eb07890ed03d5eab2dbe9 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Mon, 23 Jun 2025 00:10:58 +0200 Subject: [PATCH 30/68] Regenerate some failing tests --- assets/outputs/json/complex.json | 2 +- assets/outputs/json/complex_keys.json | 2 +- assets/outputs/toml/complex.toml | 2 +- assets/outputs/toml/complex_keys.toml | 2 +- assets/outputs/yaml/complex.yml | 2 +- benches/serde.rs | 2 +- tests/de_tests.rs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/assets/outputs/json/complex.json b/assets/outputs/json/complex.json index ae476ef..89d0f90 100644 --- a/assets/outputs/json/complex.json +++ b/assets/outputs/json/complex.json @@ -5,12 +5,12 @@ "full": "John Smith" }, "age": 32, - "placeholder": null, "employment": { "employed": true, "name": "Postman", "sinceYear": 2019 }, + "placeholder": null, "parents": { "father": { "birthday": { diff --git a/assets/outputs/json/complex_keys.json b/assets/outputs/json/complex_keys.json index 3fac302..9b212be 100644 --- a/assets/outputs/json/complex_keys.json +++ b/assets/outputs/json/complex_keys.json @@ -2,7 +2,7 @@ "with_underscore": 0, "with-dash": 1, "with_🌽": 2, - "!\"£$%^&*()_": 3, + "!£$%^&*()_": 3, "j12345": 4, "foo": { "bar-baz": "hello" diff --git a/assets/outputs/toml/complex.toml b/assets/outputs/toml/complex.toml index 3cf09b6..2717888 100644 --- a/assets/outputs/toml/complex.toml +++ b/assets/outputs/toml/complex.toml @@ -7,7 +7,7 @@ favourites = [ "Postman", 4.73753, false, - { hello = "world" }, + { hello = "world", food = { favourite = "egg", hated = "beef" } }, ] empty2 = [] diff --git a/assets/outputs/toml/complex_keys.toml b/assets/outputs/toml/complex_keys.toml index d550ef7..4647d38 100644 --- a/assets/outputs/toml/complex_keys.toml +++ b/assets/outputs/toml/complex_keys.toml @@ -1,7 +1,7 @@ with_underscore = 0 with-dash = 1 "with_🌽" = 2 -'!£$%^&*()_' = 3 +"!£$%^&*()_" = 3 j12345 = 4 [foo] diff --git a/assets/outputs/yaml/complex.yml b/assets/outputs/yaml/complex.yml index 8fbbc46..1c34547 100644 --- a/assets/outputs/yaml/complex.yml +++ b/assets/outputs/yaml/complex.yml @@ -3,11 +3,11 @@ name: last: Smith full: John Smith age: 32 -placeholder: null employment: employed: true name: Postman sinceYear: 2019 +placeholder: null parents: father: birthday: diff --git a/benches/serde.rs b/benches/serde.rs index b37a030..6f2b301 100644 --- a/benches/serde.rs +++ b/benches/serde.rs @@ -213,7 +213,7 @@ struct ComplexParentsFatherBirthday { #[derive(Deserialize, Debug, PartialEq)] struct ComplexKeys { - #[serde(rename = "!\"£$%^&*()_")] + #[serde(rename = "!£$%^&*()_")] symbols: i64, #[serde(rename = "apple-pie")] apple_pie: ComplexKeysApplePie, diff --git a/tests/de_tests.rs b/tests/de_tests.rs index b039970..77d86f6 100644 --- a/tests/de_tests.rs +++ b/tests/de_tests.rs @@ -237,7 +237,7 @@ struct ComplexParentsFatherBirthday { #[derive(Deserialize, Debug, PartialEq)] struct ComplexKeys { - #[serde(rename = "!\"£$%^&*()_")] + #[serde(rename = "!£$%^&*()_")] symbols: i64, #[serde(rename = "apple-pie")] apple_pie: ComplexKeysApplePie, From 552fd802077f2b0429b00731e97e99fec9106e52 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Mon, 23 Jun 2025 00:42:38 +0200 Subject: [PATCH 31/68] Add multiline string parsing --- cli/src/error.rs | 1 + src/de.rs | 74 ++++++++++++++++++++++++++++++++++++++++++------ src/error.rs | 3 ++ 3 files changed, 69 insertions(+), 9 deletions(-) diff --git a/cli/src/error.rs b/cli/src/error.rs index 4c41a6a..b77e9b5 100644 --- a/cli/src/error.rs +++ b/cli/src/error.rs @@ -25,6 +25,7 @@ impl ExitCode for CornError { CornError::InvalidSpreadError => 7, CornError::InvalidInterpolationError => 8, CornError::DeserializationError(_) => 5, + CornError::ParseError(_) => 6, } } } diff --git a/src/de.rs b/src/de.rs index 112b80b..0f49aae 100644 --- a/src/de.rs +++ b/src/de.rs @@ -23,19 +23,15 @@ impl<'de> Deserializer<'de> { pub fn parse(input: &str) -> Result { let mut lexer = Lexer::new(input); let parser = RootParser::new(); - let Root { inputs, object } = parser.parse(input, &mut lexer).expect("Failed to parse"); // FIXME: handler errors + let Root { inputs, object } = parser + .parse(input, &mut lexer) + .map_err(|err| Error::ParseError(err.to_string()))?; Self::resolve_entry(&Entry::Object(object), &inputs) } pub fn from_str(input: &'de str) -> Result { - let mut lexer = Lexer::new(input); - let parser = RootParser::new(); - let Root { inputs, object } = parser.parse(input, &mut lexer).expect("Failed to parse"); // FIXME: handler errors - - Ok(Self { - value: Self::resolve_entry(&Entry::Object(object), &inputs)?, - }) + Self::parse(input).map(|value| Self { value }) } fn with_value(value: BorrowedValue<'de>) -> Self { @@ -68,7 +64,9 @@ impl<'de> Deserializer<'de> { } } - Ok(BorrowedValue::String(Cow::Owned(base))) + Ok(BorrowedValue::String(Cow::Owned( + Self::process_multiline_string(&base), + ))) } Entry::Integer(integer) => Ok(BorrowedValue::Integer(*integer)), Entry::Float(float) => Ok(BorrowedValue::Float(*float)), @@ -171,6 +169,64 @@ impl<'de> Deserializer<'de> { Ok(()) } + fn process_multiline_string(input: &str) -> String { + if !input.starts_with('\n') { + return input.to_string(); + } + + let lines: Vec<&str> = input.lines().collect(); + if lines.len() < 3 { + // Need at least: empty, content, empty/content + return input.to_string(); + } + + // Skip first empty line and handle last line (may be empty or just whitespace) + let mut content_lines: Vec<&str> = lines.iter().skip(1).copied().collect(); + + // Remove trailing lines that are empty or only whitespace + while let Some(&last) = content_lines.last() { + if last.trim().is_empty() { + content_lines.pop(); + } else { + break; + } + } + + if content_lines.is_empty() { + return String::new(); + } + + // Find minimum indentation of non-empty lines + let min_indent = content_lines + .iter() + .filter(|line| !line.trim().is_empty()) + .map(|line| line.len() - line.trim_start().len()) + .min() + .unwrap_or(0); + + // Remove minimum indentation and join with newlines + let result_lines: Vec<&str> = content_lines + .iter() + .map(|line| { + if line.trim().is_empty() { + "" + } else if line.len() >= min_indent { + &line[min_indent..] + } else { + line + } + }) + .collect(); + + let mut result = result_lines.join("\n"); + + if !result.is_empty() { + result.push('\n'); + } + + result + } + fn resolve_input<'input>( input: &str, inputs: &Inputs<'input>, diff --git a/src/error.rs b/src/error.rs index 5ed32bf..c34b70b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -19,6 +19,9 @@ pub enum Error { #[error("failed to deserialize input: {0}")] DeserializationError(String), + + #[error("failed to parse input: {0}")] + ParseError(String), } impl serde::de::Error for Error { From 439bf4a134fe5ff76164de856b4e1f24ca6e9a00 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Mon, 23 Jun 2025 00:42:57 +0200 Subject: [PATCH 32/68] Fix toml and yaml string tests --- assets/outputs/toml/string.toml | 6 +++--- assets/outputs/yaml/string.yml | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/assets/outputs/toml/string.toml b/assets/outputs/toml/string.toml index f4cc605..233fbf6 100644 --- a/assets/outputs/toml/string.toml +++ b/assets/outputs/toml/string.toml @@ -1,7 +1,7 @@ foo = "bar" -bar = ''' -"\ -''' +bar = """ +"\\ +\r\t""" baz = "a" qux = "" diff --git a/assets/outputs/yaml/string.yml b/assets/outputs/yaml/string.yml index f1649d4..6a78af1 100644 --- a/assets/outputs/yaml/string.yml +++ b/assets/outputs/yaml/string.yml @@ -1,6 +1,5 @@ foo: bar -bar: | - "\ +bar: "\"\\\n\r\t" baz: a qux: '' From 483426171645c3d3ed26f72c63e6d92045bec15a Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Mon, 23 Jun 2025 01:04:12 +0200 Subject: [PATCH 33/68] Implement escaped quoted keys --- src/de.rs | 34 +++++++++++++++++++++++----------- src/value/mod.rs | 4 ++-- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/de.rs b/src/de.rs index 0f49aae..0ba46c6 100644 --- a/src/de.rs +++ b/src/de.rs @@ -77,9 +77,23 @@ impl<'de> Deserializer<'de> { for pair_or_spread in &obj.pairs { match pair_or_spread { PairOrSpread::Pair(key, value) => { + fn unescape_key(key: &str) -> Cow { + if key.contains("\\'") { + Cow::Owned(key.replace("\\'", "'")) + } else { + Cow::Borrowed(key) + } + } + + let processed_segments: Vec> = key + .segments + .iter() + .map(|segment| unescape_key(segment)) + .collect(); + Self::insert_at_path( &mut resolved_object, - &key.segments, + &processed_segments, Self::resolve_entry(value, inputs)?, )?; } @@ -136,8 +150,8 @@ impl<'de> Deserializer<'de> { } fn insert_at_path<'input>( - obj: &mut IndexMap<&'input str, BorrowedValue<'input>>, - path: &[&'input str], + obj: &mut BorrowedObject<'input>, + path: &[Cow<'input, str>], value: BorrowedValue<'input>, ) -> Result<(), Error> { if path.is_empty() { @@ -145,13 +159,13 @@ impl<'de> Deserializer<'de> { } if path.len() == 1 { - obj.insert(path[0], value); + obj.insert(path[0].clone(), value); return Ok(()); } let (first, rest) = path.split_first().unwrap(); let entry = obj - .entry(first) + .entry(first.clone()) .or_insert_with(|| BorrowedValue::Object(indexmap::IndexMap::new())); match entry { @@ -544,12 +558,12 @@ impl<'de> de::SeqAccess<'de> for SeqAccess<'de> { } struct MapAccess<'de> { - items: indexmap::map::IntoIter<&'de str, BorrowedValue<'de>>, + items: indexmap::map::IntoIter, BorrowedValue<'de>>, current_value: Option>, } impl<'de> MapAccess<'de> { - fn new(items: IndexMap<&'de str, BorrowedValue<'de>>) -> Self { + fn new(items: IndexMap, BorrowedValue<'de>>) -> Self { Self { items: items.into_iter(), current_value: None, @@ -567,8 +581,7 @@ impl<'de> de::MapAccess<'de> for MapAccess<'de> { match self.items.next() { Some((key, value)) => { self.current_value = Some(value); - let mut key_deserializer = - Deserializer::with_value(BorrowedValue::String(Cow::Borrowed(key))); + let mut key_deserializer = Deserializer::with_value(BorrowedValue::String(key)); seed.deserialize(&mut key_deserializer).map(Some) } None => Ok(None), @@ -616,8 +629,7 @@ impl<'de> de::EnumAccess<'de> for EnumAccess<'de> { } let (key, value) = self.object.into_iter().next().unwrap(); - let mut key_deserializer = - Deserializer::with_value(BorrowedValue::String(Cow::Borrowed(key))); + let mut key_deserializer = Deserializer::with_value(BorrowedValue::String(key)); let variant = seed.deserialize(&mut key_deserializer)?; Ok((variant, VariantAccess::new(value))) diff --git a/src/value/mod.rs b/src/value/mod.rs index 5dd08d8..d9adde0 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -12,7 +12,7 @@ use crate::Error; /// Object: Key-value collection that preserves insertion order pub type Object = IndexMap; -pub type BorrowedObject<'input> = IndexMap<&'input str, BorrowedValue<'input>>; +pub type BorrowedObject<'input> = IndexMap, BorrowedValue<'input>>; /// Represents a Corn configuration value. /// @@ -67,7 +67,7 @@ impl BorrowedValue<'_> { BorrowedValue::Object(object) => Value::Object( object .into_iter() - .map(|(k, v)| (k.to_owned(), Value::from(v))) + .map(|(k, v)| (k.into_owned(), Value::from(v))) .collect(), ), } From a84866ba0c037ae032a660ea541e82e0312d6839 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Mon, 23 Jun 2025 01:10:12 +0200 Subject: [PATCH 34/68] Fix ci --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de303fa..7ec4378 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: run: cargo fmt --check --all - name: Check Clippy - run: cargo clippy --workspace --all-targets --features wasm,lua54,bench + run: cargo clippy --workspace --all-targets --features wasm,lua54 build: runs-on: ${{ matrix.os }} @@ -75,8 +75,8 @@ jobs: - name: Build run: cargo build --features wasm - - name: Wasm-Pack Test - run: wasm-pack test --node + # - name: Wasm-Pack Test + # run: wasm-pack test --node build-lua: runs-on: ubuntu-latest From 4dc7347cbb376bfc9cb6fd6c328b9202468d0ea0 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Mon, 23 Jun 2025 01:11:45 +0200 Subject: [PATCH 35/68] Fix clippy --- src/de.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/de.rs b/src/de.rs index 0ba46c6..6fbaac6 100644 --- a/src/de.rs +++ b/src/de.rs @@ -30,6 +30,7 @@ impl<'de> Deserializer<'de> { Self::resolve_entry(&Entry::Object(object), &inputs) } + #[allow(clippy::should_implement_trait)] pub fn from_str(input: &'de str) -> Result { Self::parse(input).map(|value| Self { value }) } From 9c2a2bf403061d8cab41aeb17a72d67c12017514 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Mon, 23 Jun 2025 05:43:56 +0200 Subject: [PATCH 36/68] Add new unicode syntax --- assets/inputs/string.corn | 2 +- assets/inputs/unicode.corn | 6 ++++++ assets/outputs/json/unicode.json | 6 ++++++ assets/outputs/toml/unicode.toml | 5 +++++ assets/outputs/yaml/unicode.yml | 5 +++++ src/lexer.rs | 4 ++-- tests/de_tests.rs | 23 +++++++++++++++++++++++ tests/parser_tests.rs | 1 + 8 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 assets/inputs/unicode.corn create mode 100644 assets/outputs/json/unicode.json create mode 100644 assets/outputs/toml/unicode.toml create mode 100644 assets/outputs/yaml/unicode.yml diff --git a/assets/inputs/string.corn b/assets/inputs/string.corn index 640240a..52a29c4 100644 --- a/assets/inputs/string.corn +++ b/assets/inputs/string.corn @@ -1,6 +1,6 @@ { foo = "bar" bar = "\"\\\n\r\t" - baz = "\u0061" + baz = "\u{0061}" qux = "" } diff --git a/assets/inputs/unicode.corn b/assets/inputs/unicode.corn new file mode 100644 index 0000000..2b027c4 --- /dev/null +++ b/assets/inputs/unicode.corn @@ -0,0 +1,6 @@ +{ + plane0 = "\u{053E}" + plane1 = "\u{10514}" + plane2 = "\u{2B77C}" + plane3 = "\u{3106C}" +} \ No newline at end of file diff --git a/assets/outputs/json/unicode.json b/assets/outputs/json/unicode.json new file mode 100644 index 0000000..f725d8c --- /dev/null +++ b/assets/outputs/json/unicode.json @@ -0,0 +1,6 @@ +{ + "plane0": "Ծ", + "plane1": "𐔔", + "plane2": "𫝼", + "plane3": "𱁬" +} diff --git a/assets/outputs/toml/unicode.toml b/assets/outputs/toml/unicode.toml new file mode 100644 index 0000000..98cf61f --- /dev/null +++ b/assets/outputs/toml/unicode.toml @@ -0,0 +1,5 @@ +plane0 = "Ծ" +plane1 = "𐔔" +plane2 = "𫝼" +plane3 = "𱁬" + diff --git a/assets/outputs/yaml/unicode.yml b/assets/outputs/yaml/unicode.yml new file mode 100644 index 0000000..d53844d --- /dev/null +++ b/assets/outputs/yaml/unicode.yml @@ -0,0 +1,5 @@ +plane0: Ծ +plane1: 𐔔 +plane2: 𫝼 +plane3: 𱁬 + diff --git a/src/lexer.rs b/src/lexer.rs index 5d2cf9e..543cd7e 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -127,7 +127,7 @@ enum StringContext<'input> { OpenBraceEscape, #[token("\\}")] CloseBraceEscape, - #[regex(r"\\u[0-9a-fA-F]{4}")] + #[regex(r"\\u\{[0-9a-fA-F]{4,6}\}")] UnicodeEscape, #[regex(r"\$\{[a-zA-Z_][a-zA-Z0-9_]*\}", |lex| lex.slice())] @@ -189,7 +189,7 @@ fn parse_literal<'input>( } StringContext::UnicodeEscape => { let slice = string_lex.slice(); - let hex_part = &slice[2..]; // Skip "\\u" + let hex_part = &slice[3..slice.len() - 1]; if let Ok(code) = u32::from_str_radix(hex_part, 16) { if let Some(unicode_char) = char::from_u32(code) { diff --git a/tests/de_tests.rs b/tests/de_tests.rs index 77d86f6..22d7649 100644 --- a/tests/de_tests.rs +++ b/tests/de_tests.rs @@ -443,6 +443,14 @@ struct ValueAfterTable { qux: bool, } +#[derive(Deserialize, Debug, PartialEq)] +struct Unicode { + plane0: String, + plane1: String, + plane2: String, + plane3: String, +} + generate_eq_tests!( (array, Array), (basic, Basic), @@ -594,3 +602,18 @@ fn null_unit() { assert_eq!(config, json_config); } + +#[test] +fn unicode() { + let test_name = "unicode"; + let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + + let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{test_name}.corn")).unwrap(); + let config = from_str::(&input).unwrap(); + + let json_input = + fs::read_to_string(format!("{root_dir}/assets/outputs/json/{test_name}.json")).unwrap(); + let json_config = serde_json::from_str(&json_input).unwrap(); + + assert_eq!(config, json_config); +} diff --git a/tests/parser_tests.rs b/tests/parser_tests.rs index ff97e62..4017816 100644 --- a/tests/parser_tests.rs +++ b/tests/parser_tests.rs @@ -98,6 +98,7 @@ generate_eq_tests!( spread, string, string_interpolation, + unicode, value_after_table, very_compact ); From 09cfb4a29772b926341ed9f919abc12b29698a55 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Mon, 23 Jun 2025 15:22:19 +0200 Subject: [PATCH 37/68] Add back wasm support --- .github/workflows/ci.yml | 4 ++-- Cargo.lock | 24 ++++++++++++++++++++++++ Cargo.toml | 17 ++++++++++++----- src/lib.rs | 2 ++ 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ec4378..5eb1784 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,8 +75,8 @@ jobs: - name: Build run: cargo build --features wasm - # - name: Wasm-Pack Test - # run: wasm-pack test --node + - name: Wasm-Pack Test + run: wasm-pack test --node --features wasm build-lua: runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index dddd47b..f12d396 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -243,6 +243,16 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + [[package]] name = "corn-cli" version = "0.10.0" @@ -551,6 +561,7 @@ name = "libcorn" version = "0.10.0" dependencies = [ "anyhow", + "console_error_panic_hook", "criterion", "indexmap", "itoa", @@ -560,11 +571,13 @@ dependencies = [ "mlua", "paste", "serde", + "serde-wasm-bindgen", "serde_bytes", "serde_json", "serde_norway", "thiserror", "toml_edit", + "wasm-bindgen", "wasm-bindgen-test", ] @@ -980,6 +993,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_bytes" version = "0.11.17" diff --git a/Cargo.toml b/Cargo.toml index 69f9191..c52e0db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,12 @@ readme = "README.md" [features] # WASM support -wasm = [] +wasm = [ + "dep:wasm-bindgen", + "dep:serde-wasm-bindgen", + "dep:console_error_panic_hook", +] + # Lua support lua51 = ["dep:mlua", "mlua/lua51"] lua52 = ["dep:mlua", "mlua/lua52"] @@ -43,9 +48,9 @@ itoa = "1.0.15" thiserror = "2.0.12" # # WASM support (optional) -# wasm-bindgen = { version = "0.2.100", optional = true } -# serde-wasm-bindgen = { version = "0.6.5", optional = true } -# console_error_panic_hook = { version = "0.1.7", optional = true } +wasm-bindgen = { version = "0.2.100", optional = true } +serde-wasm-bindgen = { version = "0.6.5", optional = true } +console_error_panic_hook = { version = "0.1.7", optional = true } # Lua support (optional) mlua = { version = "0.10.5", features = [ @@ -64,9 +69,11 @@ serde_norway = "0.9.42" serde_bytes = "0.11.17" toml_edit = { version = "0.22.27", features = ["serde"] } anyhow = "1.0.97" -criterion = { version = "0.6.0", features = ["html_reports"] } paste = "1.0.15" +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +criterion = { version = "0.6.0", features = ["html_reports"] } + [profile.release] lto = true codegen-units = 1 diff --git a/src/lib.rs b/src/lib.rs index 406d59a..4affd20 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,8 @@ mod de; feature = "luajit52" ))] mod lua; +#[cfg(feature = "wasm")] +mod wasm; mod error; pub(crate) mod value; From 2e2d6e44f3af6dc19d7edcebfabcbd982ad138b7 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Mon, 23 Jun 2025 15:24:35 +0200 Subject: [PATCH 38/68] Fix wasm-pack not building on newer rust versions --- Cargo.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index c52e0db..f9a845e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -82,3 +82,9 @@ strip = true [[bench]] name = "serde" harness = false + +[package.metadata.wasm-pack.profile.profiling] +wasm-opt = ['-O', '--enable-bulk-memory'] + +[package.metadata.wasm-pack.profile.release] +wasm-opt = ['-O', '--enable-bulk-memory'] From 3e63ce5190a0a7dd8fd5a8b3241c81008a682019 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 15:18:40 +0200 Subject: [PATCH 39/68] Fix wrong manifest authors --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f9a845e..a2d5fa2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ repository = "https://github.com/JakeStanger/corn" categories = ["config", "parsing"] keywords = ["configuration", "language", "wasm", "peg"] authors = [ - "Jake Stanger ", + "Jake Stanger ", "Matilde Morrone ", ] homepage = "https://cornlang.dev/" From 00304a6e5ce00bc9a86ee194d6e0997863dde472 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 15:20:32 +0200 Subject: [PATCH 40/68] Expand quoted_keys test --- assets/inputs/quoted_keys.corn | 1 + assets/outputs/json/quoted_keys.json | 3 ++- assets/outputs/toml/quoted_keys.toml | 1 + assets/outputs/yaml/quoted_keys.yml | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/assets/inputs/quoted_keys.corn b/assets/inputs/quoted_keys.corn index da61425..dd3e0f6 100644 --- a/assets/inputs/quoted_keys.corn +++ b/assets/inputs/quoted_keys.corn @@ -4,4 +4,5 @@ 'with spaces' = true 'escaped\'quote' = false 'escaped=equals' = -3 + 'normal"quotes' = "funny" } \ No newline at end of file diff --git a/assets/outputs/json/quoted_keys.json b/assets/outputs/json/quoted_keys.json index c1bc3f5..a0ed5e5 100644 --- a/assets/outputs/json/quoted_keys.json +++ b/assets/outputs/json/quoted_keys.json @@ -7,5 +7,6 @@ }, "with spaces": true, "escaped'quote": false, - "escaped=equals": -3 + "escaped=equals": -3, + "normal\"quotes": "funny" } diff --git a/assets/outputs/toml/quoted_keys.toml b/assets/outputs/toml/quoted_keys.toml index 06bc629..d95a19d 100644 --- a/assets/outputs/toml/quoted_keys.toml +++ b/assets/outputs/toml/quoted_keys.toml @@ -2,6 +2,7 @@ "with spaces" = true "escaped'quote" = false "escaped=equals" = -3 +'normal"quotes' = "funny" ["green.eggs".and] ham = "hello world" diff --git a/assets/outputs/yaml/quoted_keys.yml b/assets/outputs/yaml/quoted_keys.yml index da5aced..8172c2d 100644 --- a/assets/outputs/yaml/quoted_keys.yml +++ b/assets/outputs/yaml/quoted_keys.yml @@ -5,4 +5,5 @@ green.eggs: with spaces: true escaped'quote: false escaped=equals: -3 +normal"quotes: funny From 582099f747a6e402329d610846bc6b6528096c91 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 15:21:19 +0200 Subject: [PATCH 41/68] Fix cli error codes --- cli/src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/src/error.rs b/cli/src/error.rs index b77e9b5..25d1028 100644 --- a/cli/src/error.rs +++ b/cli/src/error.rs @@ -20,12 +20,12 @@ pub trait ExitCode { impl ExitCode for CornError { fn get_exit_code(&self) -> i32 { match self { + CornError::ParseError(_) => 1, CornError::Io(_) => 3, CornError::InputResolveError(_) => 2, CornError::InvalidSpreadError => 7, CornError::InvalidInterpolationError => 8, CornError::DeserializationError(_) => 5, - CornError::ParseError(_) => 6, } } } From c205fec8c2514b625e0c0dab003e6a2f9971c1bd Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 15:24:58 +0200 Subject: [PATCH 42/68] Cleanup Value docs --- src/value/mod.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/value/mod.rs b/src/value/mod.rs index d9adde0..8f65898 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -16,14 +16,7 @@ pub type BorrowedObject<'input> = IndexMap, BorrowedValue<'inpu /// Represents a Corn configuration value. /// -/// This enum encompasses all possible value types in the Corn language specification: -/// - String: UTF-8 string values -/// - Integer: 64-bit signed integers -/// - Float: 64-bit floating point numbers -/// - Boolean: true/false values -/// - Object: Key-value collection that preserves insertion order -/// - Array: Ordered collections of values -/// - Null: Represents absence of a value +/// This enum encompasses all possible value types in the Corn language specification #[derive(Debug, Clone)] pub enum Value { /// A UTF-8 string value From d7858fc930dc40fcfdc21652010f3d67517e069b Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 15:28:50 +0200 Subject: [PATCH 43/68] Implement PartialEq for Value --- src/value/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/value/mod.rs b/src/value/mod.rs index 8f65898..ba0a051 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -17,7 +17,7 @@ pub type BorrowedObject<'input> = IndexMap, BorrowedValue<'inpu /// Represents a Corn configuration value. /// /// This enum encompasses all possible value types in the Corn language specification -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum Value { /// A UTF-8 string value String(String), @@ -35,7 +35,7 @@ pub enum Value { Null, } -#[derive(Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum BorrowedValue<'input> { String(Cow<'input, str>), Integer(Integer), From d1b16652744f1727cad82355828d3df877defd88 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 15:35:24 +0200 Subject: [PATCH 44/68] Fix extra character in manifest --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a2d5fa2..2f71b4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,7 @@ lalrpop-util = { version = "0.22.2", features = ["lexer"] } itoa = "1.0.15" thiserror = "2.0.12" -# # WASM support (optional) +# WASM support (optional) wasm-bindgen = { version = "0.2.100", optional = true } serde-wasm-bindgen = { version = "0.6.5", optional = true } console_error_panic_hook = { version = "0.1.7", optional = true } From d4bb577e3fadf9b13609e1888993ae2fbe090193 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 15:38:04 +0200 Subject: [PATCH 45/68] Fix wrong errors being used --- src/de.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/de.rs b/src/de.rs index 6fbaac6..6cde4fe 100644 --- a/src/de.rs +++ b/src/de.rs @@ -106,18 +106,10 @@ impl<'de> Deserializer<'de> { resolved_object.insert(k, v); } } - _ => { - return Err(Error::DeserializationError(format!( - "Cannot spread non-object type: {}", - name - ))) - } + _ => return Err(Error::InvalidSpreadError), } } else { - return Err(Error::DeserializationError(format!( - "Undefined input for spread: {}", - name - ))); + return Err(Error::InputResolveError(name.to_string())); } } } From 9b0b711a3cad0454755b034a7831d19b963f9b43 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 15:42:53 +0200 Subject: [PATCH 46/68] Use more efficient memory management when resolving objects --- src/de.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/de.rs b/src/de.rs index 6cde4fe..4e06de0 100644 --- a/src/de.rs +++ b/src/de.rs @@ -92,6 +92,8 @@ impl<'de> Deserializer<'de> { .map(|segment| unescape_key(segment)) .collect(); + resolved_object.reserve_exact(processed_segments.len()); + Self::insert_at_path( &mut resolved_object, &processed_segments, @@ -102,9 +104,7 @@ impl<'de> Deserializer<'de> { if let Some(spread_entry) = inputs.get(name) { match Self::resolve_entry(spread_entry, inputs)? { BorrowedValue::Object(spread_obj) => { - for (k, v) in spread_obj { - resolved_object.insert(k, v); - } + resolved_object.extend(spread_obj); } _ => return Err(Error::InvalidSpreadError), } @@ -115,6 +115,8 @@ impl<'de> Deserializer<'de> { } } + resolved_object.shrink_to_fit(); + Ok(BorrowedValue::Object(resolved_object)) } Entry::Array(items) => { From 8a2579336995f81b3c4c42256dce147d647c109b Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 15:45:17 +0200 Subject: [PATCH 47/68] Use expect instead of unwrap when inserting objects --- src/de.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de.rs b/src/de.rs index 4e06de0..11e568e 100644 --- a/src/de.rs +++ b/src/de.rs @@ -158,7 +158,7 @@ impl<'de> Deserializer<'de> { return Ok(()); } - let (first, rest) = path.split_first().unwrap(); + let (first, rest) = path.split_first().expect("Internal splitting error"); let entry = obj .entry(first.clone()) .or_insert_with(|| BorrowedValue::Object(indexmap::IndexMap::new())); From 44045128cfdf1d953d1e47e588b32e4781a7f82b Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 15:45:53 +0200 Subject: [PATCH 48/68] Remove unnecessary fully qualified syntax --- src/de.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de.rs b/src/de.rs index 11e568e..3bd4f95 100644 --- a/src/de.rs +++ b/src/de.rs @@ -161,7 +161,7 @@ impl<'de> Deserializer<'de> { let (first, rest) = path.split_first().expect("Internal splitting error"); let entry = obj .entry(first.clone()) - .or_insert_with(|| BorrowedValue::Object(indexmap::IndexMap::new())); + .or_insert_with(|| BorrowedValue::Object(IndexMap::new())); match entry { BorrowedValue::Object(nested_obj) => { From 38a0a7777e7508d95d83ab1350d89c6f2b412453 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 15:48:47 +0200 Subject: [PATCH 49/68] Replace another unwrap with an expect --- src/de.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/de.rs b/src/de.rs index 3bd4f95..f7e65df 100644 --- a/src/de.rs +++ b/src/de.rs @@ -623,7 +623,12 @@ impl<'de> de::EnumAccess<'de> for EnumAccess<'de> { ))); } - let (key, value) = self.object.into_iter().next().unwrap(); + let (key, value) = self + .object + .into_iter() + .next() + .expect("Internal variant error"); + let mut key_deserializer = Deserializer::with_value(BorrowedValue::String(key)); let variant = seed.deserialize(&mut key_deserializer)?; From e1bbd44679aea465f8f6e70d2696e0bee72958f4 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 16:46:37 +0200 Subject: [PATCH 50/68] Enhanced integer support --- assets/inputs/integer.corn | 39 +++++++++++++-- assets/outputs/json/integer.json | 30 ++++++++++-- assets/outputs/toml/integer.toml | 30 ++++++++++-- assets/outputs/yaml/integer.yml | 30 ++++++++++-- src/lexer.rs | 83 ++++++++++++++++++++++++++++++-- tests/de_tests.rs | 39 +++++++++++++-- 6 files changed, 231 insertions(+), 20 deletions(-) diff --git a/assets/inputs/integer.corn b/assets/inputs/integer.corn index d02fb21..8673268 100644 --- a/assets/inputs/integer.corn +++ b/assets/inputs/integer.corn @@ -1,5 +1,38 @@ { - foo = 42 - bar = 0xfafafa - baz = 1_000_000 + // Basic decimal integers + positive_decimal = 42 + negative_decimal = -123 + zero = 0 + + // Decimal with underscores + large_decimal = 1_000_000 + negative_large_decimal = -1_234_567 + decimal_with_underscores = 12_34_56 + + // Hexadecimal integers + hex_lowercase = 0xfafafa + hex_uppercase = 0xFF + hex_mixed = 0xAbCdEf + negative_hex = -0xABC + hex_with_underscores = 0xFA_FA_FA + negative_hex_underscores = -0xAB_CD_EF + hex_single_digit = 0xF + hex_zero = 0x0 + + // Octal integers + octal_basic = 0o755 + octal_zero = 0o0 + negative_octal = -0o123 + octal_with_underscores = 0o12_34_56 + negative_octal_underscores = -0o76_54_32 + octal_single_digit = 0o7 + + // Binary integers + binary_basic = 0b1010 + binary_zero = 0b0 + negative_binary = -0b1100 + binary_with_underscores = 0b1010_1100_1111 + negative_binary_underscores = -0b1100_0011 + binary_single_digit = 0b1 + binary_all_ones = 0b1111 } diff --git a/assets/outputs/json/integer.json b/assets/outputs/json/integer.json index b5ceb63..5855b47 100644 --- a/assets/outputs/json/integer.json +++ b/assets/outputs/json/integer.json @@ -1,5 +1,29 @@ { - "foo": 42, - "bar": 16448250, - "baz": 1000000 + "positive_decimal": 42, + "negative_decimal": -123, + "zero": 0, + "large_decimal": 1000000, + "negative_large_decimal": -1234567, + "decimal_with_underscores": 123456, + "hex_lowercase": 16448250, + "hex_uppercase": 255, + "hex_mixed": 11259375, + "negative_hex": -2748, + "hex_with_underscores": 16448250, + "negative_hex_underscores": -11259375, + "hex_single_digit": 15, + "hex_zero": 0, + "octal_basic": 493, + "octal_zero": 0, + "negative_octal": -83, + "octal_with_underscores": 42798, + "negative_octal_underscores": -256794, + "octal_single_digit": 7, + "binary_basic": 10, + "binary_zero": 0, + "negative_binary": -12, + "binary_with_underscores": 2767, + "negative_binary_underscores": -195, + "binary_single_digit": 1, + "binary_all_ones": 15 } diff --git a/assets/outputs/toml/integer.toml b/assets/outputs/toml/integer.toml index 23bf8f5..c35536e 100644 --- a/assets/outputs/toml/integer.toml +++ b/assets/outputs/toml/integer.toml @@ -1,4 +1,28 @@ -foo = 42 -bar = 16448250 -baz = 1000000 +positive_decimal = 42 +negative_decimal = -123 +zero = 0 +large_decimal = 1000000 +negative_large_decimal = -1234567 +decimal_with_underscores = 123456 +hex_lowercase = 16448250 +hex_uppercase = 255 +hex_mixed = 11259375 +negative_hex = -2748 +hex_with_underscores = 16448250 +negative_hex_underscores = -11259375 +hex_single_digit = 15 +hex_zero = 0 +octal_basic = 493 +octal_zero = 0 +negative_octal = -83 +octal_with_underscores = 42798 +negative_octal_underscores = -256794 +octal_single_digit = 7 +binary_basic = 10 +binary_zero = 0 +negative_binary = -12 +binary_with_underscores = 2767 +negative_binary_underscores = -195 +binary_single_digit = 1 +binary_all_ones = 15 diff --git a/assets/outputs/yaml/integer.yml b/assets/outputs/yaml/integer.yml index e76f2c1..f2d1400 100644 --- a/assets/outputs/yaml/integer.yml +++ b/assets/outputs/yaml/integer.yml @@ -1,4 +1,28 @@ -foo: 42 -bar: 16448250 -baz: 1000000 +positive_decimal: 42 +negative_decimal: -123 +zero: 0 +large_decimal: 1000000 +negative_large_decimal: -1234567 +decimal_with_underscores: 123456 +hex_lowercase: 16448250 +hex_uppercase: 255 +hex_mixed: 11259375 +negative_hex: -2748 +hex_with_underscores: 16448250 +negative_hex_underscores: -11259375 +hex_single_digit: 15 +hex_zero: 0 +octal_basic: 493 +octal_zero: 0 +negative_octal: -83 +octal_with_underscores: 42798 +negative_octal_underscores: -256794 +octal_single_digit: 7 +binary_basic: 10 +binary_zero: 0 +negative_binary: -12 +binary_with_underscores: 2767 +negative_binary_underscores: -195 +binary_single_digit: 1 +binary_all_ones: 15 diff --git a/src/lexer.rs b/src/lexer.rs index 543cd7e..b37aae7 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -85,10 +85,11 @@ pub enum Token<'input> { #[token("true", |_| true)] Boolean(bool), - #[regex(r"-[0-9]+(_[0-9]+)*", |lex| lex.slice().replace("_", "").parse::().map(Integer::from))] - #[regex(r"[0-9]+(_[0-9]+)*", |lex| lex.slice().replace("_", "").parse::().map(Integer::from))] - // FIXME: this is a mess sob - #[regex(r"0x[0-9a-fA-F][_0-9a-fA-F]*", |lex| i64::from_str_radix(&lex.slice().trim_start_matches("0x").replace("_", ""), 16).map(Integer::from))] + #[regex(r"-?0x[0-9a-fA-F]+(_[0-9a-fA-F]+)*", parse_hexadecimal)] + #[regex(r"-?0o[0-7]+(_[0-7]+)*", parse_octal)] + #[regex(r"-?0b[01]+(_[01]+)*", parse_binary)] + #[regex(r"-[0-9]+(_[0-9]+)*", parse_negative_decimal)] + #[regex(r"[0-9]+(_[0-9]+)*", parse_positive_decimal)] Integer(Integer), #[regex(r"-?[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?", |lex| lex.slice().parse::())] @@ -100,10 +101,82 @@ pub enum Token<'input> { #[token("\"", parse_literal)] Literal(Vec>), - #[regex(r#"'(?:[^'\\]|\\.)*'|[^\s.=0-9\[\]{}"'][^\s.=\[\]{}"']*"#, |lex| lex.slice().trim_matches('\''))] + #[regex(r#"'(?:[^'\\]|\\.)*'|[^\s.=0-9\[\]{}"'-][^\s.=\[\]{}"']*"#, |lex| lex.slice().trim_matches('\''))] Key(&'input str), } +fn parse_positive_decimal<'input>( + lex: &mut logos::Lexer<'input, Token<'input>>, +) -> Result { + lex.slice() + .replace("_", "") + .parse::() + .map(Integer::from) +} + +fn parse_negative_decimal<'input>( + lex: &mut logos::Lexer<'input, Token<'input>>, +) -> Result { + lex.slice() + .replace("_", "") + .parse::() + .map(Integer::from) +} + +fn parse_hexadecimal<'input>( + lex: &mut logos::Lexer<'input, Token<'input>>, +) -> Result { + let input = lex.slice().replace("_", ""); + let is_negative = input.starts_with('-'); + let hex_part = if is_negative { + &input[3..] + } else { + &input[2..] + }; + + if is_negative { + i64::from_str_radix(hex_part, 16).map(|n| Integer::from(-n)) + } else { + u64::from_str_radix(hex_part, 16).map(Integer::from) + } +} + +fn parse_octal<'input>( + lex: &mut logos::Lexer<'input, Token<'input>>, +) -> Result { + let input = lex.slice().replace("_", ""); + let is_negative = input.starts_with('-'); + let octal_part = if is_negative { + &input[3..] + } else { + &input[2..] + }; + + if is_negative { + i64::from_str_radix(octal_part, 8).map(|n| Integer::from(-n)) + } else { + u64::from_str_radix(octal_part, 8).map(Integer::from) + } +} + +fn parse_binary<'input>( + lex: &mut logos::Lexer<'input, Token<'input>>, +) -> Result { + let input = lex.slice().replace("_", ""); + let is_negative = input.starts_with('-'); + let binary_part = if is_negative { + &input[3..] + } else { + &input[2..] + }; + + if is_negative { + i64::from_str_radix(binary_part, 2).map(|n| Integer::from(-n)) + } else { + u64::from_str_radix(binary_part, 2).map(Integer::from) + } +} + #[derive(Logos, Debug, PartialEq, Clone)] enum StringContext<'input> { #[token("\"")] diff --git a/tests/de_tests.rs b/tests/de_tests.rs index 22d7649..30e23f8 100644 --- a/tests/de_tests.rs +++ b/tests/de_tests.rs @@ -289,9 +289,42 @@ struct InputDob { #[derive(Deserialize, Debug, PartialEq)] struct Integer { - foo: i64, - bar: i64, - baz: i64, + // Basic decimal integers + positive_decimal: i64, + negative_decimal: i64, + zero: i64, + + // Decimal with underscores + large_decimal: i64, + negative_large_decimal: i64, + decimal_with_underscores: i64, + + // Hexadecimal integers + hex_lowercase: i64, + hex_uppercase: i64, + hex_mixed: i64, + negative_hex: i64, + hex_with_underscores: i64, + negative_hex_underscores: i64, + hex_single_digit: i64, + hex_zero: i64, + + // Octal integers + octal_basic: i64, + octal_zero: i64, + negative_octal: i64, + octal_with_underscores: i64, + negative_octal_underscores: i64, + octal_single_digit: i64, + + // Binary integers + binary_basic: i64, + binary_zero: i64, + negative_binary: i64, + binary_with_underscores: i64, + negative_binary_underscores: i64, + binary_single_digit: i64, + binary_all_ones: i64, } #[derive(Deserialize, Debug, PartialEq)] From 985c9f3332de8d78fb2828670999b09195288d2b Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 16:51:21 +0200 Subject: [PATCH 51/68] Renamed IntegerType variants to be more reflective of their purpose --- src/value/integer.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/value/integer.rs b/src/value/integer.rs index 005032c..a9acd9b 100644 --- a/src/value/integer.rs +++ b/src/value/integer.rs @@ -21,22 +21,22 @@ impl Debug for Integer { impl Display for Integer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self.inner { - IntegerType::Negative(n) => f.write_str(itoa::Buffer::new().format(n)), - IntegerType::Positive(n) => f.write_str(itoa::Buffer::new().format(n)), + IntegerType::Signed(n) => f.write_str(itoa::Buffer::new().format(n)), + IntegerType::Unsigned(n) => f.write_str(itoa::Buffer::new().format(n)), } } } #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] enum IntegerType { - Negative(i64), - Positive(u64), + Signed(i64), + Unsigned(u64), } impl From for Integer { fn from(value: i64) -> Self { Self { - inner: IntegerType::Negative(value), + inner: IntegerType::Signed(value), } } } @@ -44,7 +44,7 @@ impl From for Integer { impl From for Integer { fn from(value: u64) -> Self { Self { - inner: IntegerType::Positive(value), + inner: IntegerType::Unsigned(value), } } } @@ -52,19 +52,19 @@ impl From for Integer { impl Integer { pub const fn is_i64(&self) -> bool { match self.inner { - IntegerType::Positive(n) => n <= i64::MAX as u64, - IntegerType::Negative(_) => true, + IntegerType::Unsigned(n) => n <= i64::MAX as u64, + IntegerType::Signed(_) => true, } } pub const fn is_u64(&self) -> bool { - matches!(self.inner, IntegerType::Positive(_)) + matches!(self.inner, IntegerType::Unsigned(_)) } pub const fn as_i64(&self) -> Option { match self.inner { - IntegerType::Negative(n) => Some(n), - IntegerType::Positive(n) => { + IntegerType::Signed(n) => Some(n), + IntegerType::Unsigned(n) => { if n <= i64::MAX as u64 { Some(n as i64) } else { @@ -76,8 +76,8 @@ impl Integer { pub const fn as_u64(&self) -> Option { match self.inner { - IntegerType::Positive(n) => Some(n), - IntegerType::Negative(_) => None, + IntegerType::Unsigned(n) => Some(n), + IntegerType::Signed(_) => None, } } } @@ -88,8 +88,8 @@ impl Serialize for Integer { S: serde::Serializer, { match self.inner { - IntegerType::Negative(integer) => serializer.serialize_i64(integer), - IntegerType::Positive(integer) => serializer.serialize_u64(integer), + IntegerType::Signed(integer) => serializer.serialize_i64(integer), + IntegerType::Unsigned(integer) => serializer.serialize_u64(integer), } } } @@ -129,8 +129,8 @@ impl<'de> de::Deserializer<'de> for Integer { V: de::Visitor<'de>, { match self.inner { - IntegerType::Negative(integer) => visitor.visit_i64(integer), - IntegerType::Positive(integer) => visitor.visit_u64(integer), + IntegerType::Signed(integer) => visitor.visit_i64(integer), + IntegerType::Unsigned(integer) => visitor.visit_u64(integer), } } From 3566c4c14ead16b214971f8d7f0bd5b7e3f5b968 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 16:57:56 +0200 Subject: [PATCH 52/68] Add missing docs --- src/de.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/de.rs b/src/de.rs index f7e65df..5412fb9 100644 --- a/src/de.rs +++ b/src/de.rs @@ -10,16 +10,19 @@ use crate::{ BorrowedObject, BorrowedValue, Error, Result, }; +/// A structure that deserializes Corn configuration values. #[derive(Clone)] pub struct Deserializer<'de> { value: BorrowedValue<'de>, } +/// Parse a Corn configuration string into a borrowed value. pub fn parse(input: &str) -> Result { Deserializer::parse(input) } impl<'de> Deserializer<'de> { + /// Parse a Corn configuration string into a borrowed value. pub fn parse(input: &str) -> Result { let mut lexer = Lexer::new(input); let parser = RootParser::new(); @@ -30,6 +33,7 @@ impl<'de> Deserializer<'de> { Self::resolve_entry(&Entry::Object(object), &inputs) } + /// Create a deserializer from a Corn configuration string. #[allow(clippy::should_implement_trait)] pub fn from_str(input: &'de str) -> Result { Self::parse(input).map(|value| Self { value }) @@ -254,6 +258,7 @@ impl<'de> Deserializer<'de> { } } +/// Deserialize a Corn configuration string into a Rust data structure. pub fn from_str<'a, T>(s: &'a str) -> Result where T: de::Deserialize<'a>, From d772ee49f66114f4026ba0c50e0095ce97851da0 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 19:57:51 +0200 Subject: [PATCH 53/68] Improve integer lexing --- src/lexer.rs | 84 +++++++++++++--------------------------------------- 1 file changed, 20 insertions(+), 64 deletions(-) diff --git a/src/lexer.rs b/src/lexer.rs index b37aae7..0e602ce 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -2,6 +2,7 @@ use std::{ borrow::Cow, fmt, num::{ParseFloatError, ParseIntError}, + str::FromStr, }; use thiserror::Error; @@ -85,11 +86,11 @@ pub enum Token<'input> { #[token("true", |_| true)] Boolean(bool), - #[regex(r"-?0x[0-9a-fA-F]+(_[0-9a-fA-F]+)*", parse_hexadecimal)] - #[regex(r"-?0o[0-7]+(_[0-7]+)*", parse_octal)] - #[regex(r"-?0b[01]+(_[01]+)*", parse_binary)] - #[regex(r"-[0-9]+(_[0-9]+)*", parse_negative_decimal)] - #[regex(r"[0-9]+(_[0-9]+)*", parse_positive_decimal)] + #[regex(r"-?0x[0-9a-fA-F]+(_[0-9a-fA-F]+)*", |lex| parse_radix_integer(lex, 16))] + #[regex(r"-?0o[0-7]+(_[0-7]+)*", |lex| parse_radix_integer(lex, 8))] + #[regex(r"-?0b[01]+(_[01]+)*", |lex| parse_radix_integer(lex, 2))] + #[regex(r"-[0-9]+(_[0-9]+)*", parse_decimal::)] + #[regex(r"[0-9]+(_[0-9]+)*", parse_decimal::)] Integer(Integer), #[regex(r"-?[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?", |lex| lex.slice().parse::())] @@ -105,75 +106,30 @@ pub enum Token<'input> { Key(&'input str), } -fn parse_positive_decimal<'input>( +/// Parse normal decimal integer, removes underscores +fn parse_decimal<'input, N>( lex: &mut logos::Lexer<'input, Token<'input>>, -) -> Result { - lex.slice() - .replace("_", "") - .parse::() - .map(Integer::from) -} - -fn parse_negative_decimal<'input>( - lex: &mut logos::Lexer<'input, Token<'input>>, -) -> Result { - lex.slice() - .replace("_", "") - .parse::() - .map(Integer::from) -} - -fn parse_hexadecimal<'input>( - lex: &mut logos::Lexer<'input, Token<'input>>, -) -> Result { - let input = lex.slice().replace("_", ""); - let is_negative = input.starts_with('-'); - let hex_part = if is_negative { - &input[3..] - } else { - &input[2..] - }; - - if is_negative { - i64::from_str_radix(hex_part, 16).map(|n| Integer::from(-n)) - } else { - u64::from_str_radix(hex_part, 16).map(Integer::from) - } -} - -fn parse_octal<'input>( - lex: &mut logos::Lexer<'input, Token<'input>>, -) -> Result { - let input = lex.slice().replace("_", ""); - let is_negative = input.starts_with('-'); - let octal_part = if is_negative { - &input[3..] - } else { - &input[2..] - }; - - if is_negative { - i64::from_str_radix(octal_part, 8).map(|n| Integer::from(-n)) - } else { - u64::from_str_radix(octal_part, 8).map(Integer::from) - } +) -> Result +where + N: Into + FromStr, +{ + lex.slice().replace("_", "").parse().map(N::into) } -fn parse_binary<'input>( +/// Parse integer with specified radix, handling negative values and underscores +fn parse_radix_integer<'input>( lex: &mut logos::Lexer<'input, Token<'input>>, + radix: u32, ) -> Result { let input = lex.slice().replace("_", ""); let is_negative = input.starts_with('-'); - let binary_part = if is_negative { - &input[3..] - } else { - &input[2..] - }; + let prefix_len = if is_negative { 3 } else { 2 }; // Skip "-0x"/"0x" etc. + let number_part = &input[prefix_len..]; if is_negative { - i64::from_str_radix(binary_part, 2).map(|n| Integer::from(-n)) + i64::from_str_radix(number_part, radix).map(|n| Integer::from(-n)) } else { - u64::from_str_radix(binary_part, 2).map(Integer::from) + u64::from_str_radix(number_part, radix).map(Integer::from) } } From 772a2e87f464a7e8fd2390142260617dac3d97f5 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 19:59:47 +0200 Subject: [PATCH 54/68] Fix formatting --- tests/de_tests.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/de_tests.rs b/tests/de_tests.rs index 30e23f8..a337801 100644 --- a/tests/de_tests.rs +++ b/tests/de_tests.rs @@ -293,12 +293,12 @@ struct Integer { positive_decimal: i64, negative_decimal: i64, zero: i64, - + // Decimal with underscores large_decimal: i64, negative_large_decimal: i64, decimal_with_underscores: i64, - + // Hexadecimal integers hex_lowercase: i64, hex_uppercase: i64, @@ -308,7 +308,7 @@ struct Integer { negative_hex_underscores: i64, hex_single_digit: i64, hex_zero: i64, - + // Octal integers octal_basic: i64, octal_zero: i64, @@ -316,7 +316,7 @@ struct Integer { octal_with_underscores: i64, negative_octal_underscores: i64, octal_single_digit: i64, - + // Binary integers binary_basic: i64, binary_zero: i64, From 3ed360d666b6fdfaf10ae86b2112eb6b344944f0 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 20:22:34 +0200 Subject: [PATCH 55/68] Improve BorrowedValue string deserialization --- src/de.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/de.rs b/src/de.rs index 5412fb9..3550370 100644 --- a/src/de.rs +++ b/src/de.rs @@ -290,7 +290,10 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { V: de::Visitor<'de>, { match self.value { - BorrowedValue::String(ref string) => visitor.visit_str(string), + BorrowedValue::String(ref string) => match string { + Cow::Borrowed(s) => visitor.visit_borrowed_str(s), + Cow::Owned(s) => visitor.visit_str(s), + }, BorrowedValue::Integer(integer) => integer.deserialize_any(visitor), BorrowedValue::Float(float) => visitor.visit_f64(float), BorrowedValue::Boolean(boolean) => visitor.visit_bool(boolean), @@ -358,7 +361,10 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { V: de::Visitor<'de>, { match self.value { - BorrowedValue::String(ref string) => visitor.visit_str(string), + BorrowedValue::String(ref string) => match string { + Cow::Borrowed(s) => visitor.visit_borrowed_str(s), + Cow::Owned(s) => visitor.visit_str(s), + }, ref value => Err(value.invalid_type("String")), } } From 3594c1d845ff6c1d1b577e88b9b409399d6841d9 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Tue, 24 Jun 2025 20:24:06 +0200 Subject: [PATCH 56/68] Add testes for borrowed inputs --- tests/borrowed_tests.rs | 191 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 tests/borrowed_tests.rs diff --git a/tests/borrowed_tests.rs b/tests/borrowed_tests.rs new file mode 100644 index 0000000..40266be --- /dev/null +++ b/tests/borrowed_tests.rs @@ -0,0 +1,191 @@ +use corn::from_str; +use serde::Deserialize; +use std::borrow::Cow; +use std::fs; + +// Borrowed structure for basic string test +#[derive(Deserialize, Debug, PartialEq)] +struct BorrowedBasic<'a> { + #[serde(borrow)] + foo: Cow<'a, str>, +} + +// Borrowed structure for string test with multiple fields +#[derive(Deserialize, Debug, PartialEq)] +struct BorrowedString<'a> { + #[serde(borrow)] + foo: Cow<'a, str>, + #[serde(borrow)] + bar: Cow<'a, str>, + #[serde(borrow)] + baz: Cow<'a, str>, + #[serde(borrow)] + qux: Cow<'a, str>, +} + +// Borrowed structure using Cow for flexible ownership +#[derive(Deserialize, Debug, PartialEq)] +struct BorrowedStringCow<'a> { + #[serde(borrow)] + foo: Cow<'a, str>, + #[serde(borrow)] + bar: Cow<'a, str>, + #[serde(borrow)] + baz: Cow<'a, str>, + #[serde(borrow)] + qux: Cow<'a, str>, +} + +// Borrowed nested structure +#[derive(Deserialize, Debug, PartialEq)] +struct BorrowedNested<'a> { + #[serde(borrow)] + name: BorrowedName<'a>, + age: i64, + #[serde(borrow)] + gender: Cow<'a, str>, +} + +#[derive(Deserialize, Debug, PartialEq)] +struct BorrowedName<'a> { + #[serde(borrow)] + first: Cow<'a, str>, + #[serde(borrow)] + last: Cow<'a, str>, + #[serde(borrow)] + full: Cow<'a, str>, +} + +// Mixed borrowed and owned fields +#[derive(Deserialize, Debug, PartialEq)] +struct BorrowedMixed<'a> { + #[serde(borrow)] + name: BorrowedNameMixed<'a>, + age: i64, + employment: BorrowedEmployment<'a>, + #[serde(borrow)] + gender: Cow<'a, str>, +} + +#[derive(Deserialize, Debug, PartialEq)] +struct BorrowedNameMixed<'a> { + #[serde(borrow)] + first: Cow<'a, str>, + #[serde(borrow)] + last: Cow<'a, str>, + // full name might be interpolated, so we use Cow + #[serde(borrow)] + full: Cow<'a, str>, +} + +#[derive(Deserialize, Debug, PartialEq)] +struct BorrowedEmployment<'a> { + employed: bool, + #[serde(borrow)] + name: Cow<'a, str>, + #[serde(rename = "sinceYear")] + since_year: i64, +} + +#[test] +fn test_borrowed_basic() { + let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + let input = fs::read_to_string(format!("{root_dir}/assets/inputs/basic.corn")).unwrap(); + + let config: BorrowedBasic = from_str(&input).unwrap(); + + assert_eq!(config.foo, "bar"); +} + +#[test] +fn test_borrowed_string() { + let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + let input = fs::read_to_string(format!("{root_dir}/assets/inputs/string.corn")).unwrap(); + + let config: BorrowedString = from_str(&input).unwrap(); + + assert_eq!(config.foo, "bar"); + assert_eq!(config.bar, "\"\\\n\r\t"); + assert_eq!(config.baz, "a"); // Unicode escape \u{0061} + assert_eq!(config.qux, ""); +} + +#[test] +fn test_borrowed_string_cow() { + let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + let input = fs::read_to_string(format!("{root_dir}/assets/inputs/string.corn")).unwrap(); + + let config: BorrowedStringCow = from_str(&input).unwrap(); + + assert_eq!(config.foo, "bar"); + assert_eq!(config.bar, "\"\\\n\r\t"); + assert_eq!(config.baz, "a"); + assert_eq!(config.qux, ""); +} + +#[test] +fn test_borrowed_nested() { + let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + let input = fs::read_to_string(format!("{root_dir}/assets/inputs/complex.corn")).unwrap(); + + let config: BorrowedNested = from_str(&input).unwrap(); + + assert_eq!(config.name.first, "John"); + assert_eq!(config.name.last, "Smith"); + assert_eq!(config.name.full, "John Smith"); + assert_eq!(config.age, 32); + assert_eq!(config.gender, "M"); +} + +#[test] +fn test_borrowed_mixed() { + let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + let input = fs::read_to_string(format!("{root_dir}/assets/inputs/complex.corn")).unwrap(); + + let config: BorrowedMixed = from_str(&input).unwrap(); + + assert_eq!(config.name.first, "John"); + assert_eq!(config.name.last, "Smith"); + assert_eq!(config.name.full, "John Smith"); + assert_eq!(config.age, 32); + assert_eq!(config.employment.employed, true); + assert_eq!(config.employment.name, "Postman"); + assert_eq!(config.employment.since_year, 2019); + assert_eq!(config.gender, "M"); +} + +// Test that demonstrates zero-copy behavior with lifetime constraints +#[test] +fn test_borrowed_lifetime_constraint() { + let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + let input = fs::read_to_string(format!("{root_dir}/assets/inputs/basic.corn")).unwrap(); + + let config: BorrowedBasic; + + { + config = from_str(&input).unwrap(); + assert_eq!(config.foo, "bar"); + } + + // config can still be used here because input is still alive + assert_eq!(config.foo, "bar"); +} + +// Test array with borrowed string elements +#[derive(Deserialize, Debug, PartialEq)] +struct BorrowedArray<'a> { + #[serde(borrow)] + foo: Vec>, +} + +#[test] +fn test_borrowed_array() { + let test_input = r#"{ foo = ["hello" "world" "test"] }"#; + + let config: BorrowedArray = from_str(test_input).unwrap(); + + assert_eq!(config.foo.len(), 3); + assert_eq!(config.foo[0], "hello"); + assert_eq!(config.foo[1], "world"); + assert_eq!(config.foo[2], "test"); +} From dc4362f5343a95847ff12aaed65ddfbef80b5594 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Fri, 25 Jul 2025 14:00:55 +0200 Subject: [PATCH 57/68] Update dependencies --- Cargo.lock | 83 +++++++++++++++++++++++++------------------------- Cargo.toml | 12 ++++---- cli/Cargo.toml | 8 ++--- 3 files changed, 52 insertions(+), 51 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f12d396..7bb15e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -190,9 +190,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.40" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" +checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" dependencies = [ "clap_builder", "clap_derive", @@ -200,9 +200,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.40" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" +checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" dependencies = [ "anstream", "anstyle", @@ -212,9 +212,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.40" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" +checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" dependencies = [ "heck", "proc-macro2", @@ -277,9 +277,9 @@ dependencies = [ [[package]] name = "criterion" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bf7af66b0989381bd0be551bd7cc91912a655a58c6918420c9527b1fd8b4679" +checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" dependencies = [ "anes", "cast", @@ -300,12 +300,12 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" dependencies = [ "cast", - "itertools 0.10.5", + "itertools 0.13.0", ] [[package]] @@ -445,9 +445,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown", @@ -460,15 +460,6 @@ 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 = "itertools" version = "0.13.0" @@ -649,9 +640,9 @@ dependencies = [ [[package]] name = "mlua" -version = "0.10.5" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f5f8fbebc7db5f671671134b9321c4b9aa9adeafccfd9a8c020ae45c6a35d0" +checksum = "de25fc513588ac1273aa8c6dc0fffee6d32c12f38dc75f5cdc74547121a107ef" dependencies = [ "bstr", "either", @@ -668,9 +659,9 @@ dependencies = [ [[package]] name = "mlua-sys" -version = "0.6.8" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380c1f7e2099cafcf40e51d3a9f20a346977587aa4d012eae1f043149a728a93" +checksum = "bcdf7c9e260ca82aaa32ac11148941952b856bb8c69aa5a9e65962f21fcb8637" dependencies = [ "cc", "cfg-if", @@ -679,11 +670,11 @@ dependencies = [ [[package]] name = "mlua_derive" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870d71c172fcf491c6b5fb4c04160619a2ee3e5a42a1402269c66bcbf1dd4deb" +checksum = "465bddde514c4eb3b50b543250e97c1d4b284fa3ef7dc0ba2992c77545dbceb2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "once_cell", "proc-macro-error2", "proc-macro2", @@ -1026,9 +1017,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" dependencies = [ "itoa", "memchr", @@ -1051,9 +1042,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.9" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" dependencies = [ "serde", ] @@ -1157,32 +1148,42 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.11" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.27" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +checksum = "d1dee9dc43ac2aaf7d3b774e2fba5148212bf2bd9374f4e50152ebe9afd03d42" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "toml_write", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97200572db069e74c512a14117b296ba0a80a30123fbbb5aa1f4a348f639ca30" +dependencies = [ "winnow", ] [[package]] -name = "toml_write" -version = "0.1.2" +name = "toml_writer" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64" [[package]] name = "typeid" diff --git a/Cargo.toml b/Cargo.toml index 2f71b4d..37990d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] # Core serde = "1.0.219" -indexmap = { version = "2.9.0", features = ["serde"] } +indexmap = { version = "2.10.0", features = ["serde"] } logos = "0.15.0" lalrpop-util = { version = "0.22.2", features = ["lexer"] } itoa = "1.0.15" @@ -53,7 +53,7 @@ serde-wasm-bindgen = { version = "0.6.5", optional = true } console_error_panic_hook = { version = "0.1.7", optional = true } # Lua support (optional) -mlua = { version = "0.10.5", features = [ +mlua = { version = "0.11.1", features = [ "module", "macros", "serialize", @@ -64,15 +64,15 @@ lalrpop = "0.22.2" [dev-dependencies] wasm-bindgen-test = { version = "0.3.50" } -serde_json = "1.0.140" +serde_json = "1.0.141" serde_norway = "0.9.42" serde_bytes = "0.11.17" -toml_edit = { version = "0.22.27", features = ["serde"] } -anyhow = "1.0.97" +toml_edit = { version = "0.23.2", features = ["serde"] } +anyhow = "1.0.98" paste = "1.0.15" [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] -criterion = { version = "0.6.0", features = ["html_reports"] } +criterion = { version = "0.7.0", features = ["html_reports"] } [profile.release] lto = true diff --git a/cli/Cargo.toml b/cli/Cargo.toml index a3b3906..e572a81 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -14,12 +14,12 @@ documentation = "https://docs.rs/corn-cli" [dependencies] # CLI dependencies -clap = { version = "4.5.31", features = ["derive", "cargo"] } +clap = { version = "4.5.41", features = ["derive", "cargo"] } colored = "3.0.0" # (De)serialization -serde = { version = "1.0.218", features = ["derive"] } -serde_json = "1.0.140" +serde = { version = "1.0.219", features = ["derive"] } +serde_json = "1.0.141" serde_norway = "0.9.42" libcorn = { version = "0.10.0", path = ".." } -toml_edit = { version = "0.22.24", features = ["serde"] } +toml_edit = { version = "0.23.2", features = ["serde"] } From 9ad20191b9bb7bb060b7bafc1ed353c06aad5459 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Fri, 25 Jul 2025 14:02:45 +0200 Subject: [PATCH 58/68] Make clippy happy --- src/de.rs | 3 +-- src/value/integer.rs | 2 +- tests/borrowed_tests.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/de.rs b/src/de.rs index 3550370..54577d6 100644 --- a/src/de.rs +++ b/src/de.rs @@ -173,8 +173,7 @@ impl<'de> Deserializer<'de> { } _ => { return Err(Error::DeserializationError(format!( - "Cannot index into non-object at key: {}", - first + "Cannot index into non-object at key: {first}" ))); } } diff --git a/src/value/integer.rs b/src/value/integer.rs index a9acd9b..7f38c67 100644 --- a/src/value/integer.rs +++ b/src/value/integer.rs @@ -14,7 +14,7 @@ pub struct Integer { impl Debug for Integer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Integer({})", self) + write!(f, "Integer({self})") } } diff --git a/tests/borrowed_tests.rs b/tests/borrowed_tests.rs index 40266be..1fc04bc 100644 --- a/tests/borrowed_tests.rs +++ b/tests/borrowed_tests.rs @@ -148,7 +148,7 @@ fn test_borrowed_mixed() { assert_eq!(config.name.last, "Smith"); assert_eq!(config.name.full, "John Smith"); assert_eq!(config.age, 32); - assert_eq!(config.employment.employed, true); + assert!(config.employment.employed); assert_eq!(config.employment.name, "Postman"); assert_eq!(config.employment.since_year, 2019); assert_eq!(config.gender, "M"); From 32c452335b2babe6dc9c4c7eda726982753bbf8e Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Wed, 27 Aug 2025 12:33:23 +0200 Subject: [PATCH 59/68] Update dependencies --- Cargo.lock | 272 +++++++++++++++++++++++++++++++------------------ Cargo.toml | 14 +-- cli/Cargo.toml | 6 +- 3 files changed, 181 insertions(+), 111 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bb15e0..0761f81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.19" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" dependencies = [ "anstyle", "anstyle-parse", @@ -49,29 +49,29 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "windows-sys", + "windows-sys 0.60.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.9" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys", + "windows-sys 0.60.2", ] [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" [[package]] name = "ascii-canvas" @@ -84,9 +84,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "beef" @@ -111,9 +111,9 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" [[package]] name = "block-buffer" @@ -136,9 +136,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.18.1" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "cast" @@ -148,18 +148,18 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.27" +version = "1.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" +checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" dependencies = [ "shlex", ] [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "ciborium" @@ -190,9 +190,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.41" +version = "4.5.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" +checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" dependencies = [ "clap_builder", "clap_derive", @@ -200,9 +200,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.41" +version = "4.5.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" +checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" dependencies = [ "anstream", "anstyle", @@ -212,9 +212,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.41" +version = "4.5.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" +checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" dependencies = [ "heck", "proc-macro2", @@ -240,7 +240,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -335,9 +335,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" @@ -424,9 +424,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" [[package]] name = "heck" @@ -434,20 +434,11 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "home" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys", -] - [[package]] name = "indexmap" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" dependencies = [ "equivalent", "hashbrown", @@ -543,9 +534,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.173" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8cfeafaffdbc32176b64fb251369d52ea9f0a8fbc6f8759edffef7b525d64bb" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "libcorn" @@ -590,18 +581,18 @@ checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "logos" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab6f536c1af4c7cc81edf73da1f8029896e7e1e16a219ef09b184e76a296f3db" +checksum = "ff472f899b4ec2d99161c51f60ff7075eeb3097069a36050d8037a6325eb8154" dependencies = [ "logos-derive", ] [[package]] name = "logos-codegen" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "189bbfd0b61330abea797e5e9276408f2edbe4f822d7ad08685d67419aafb34e" +checksum = "192a3a2b90b0c05b27a0b2c43eecdb7c415e29243acc3f89cc8247a5b693045c" dependencies = [ "beef", "fnv", @@ -615,9 +606,9 @@ dependencies = [ [[package]] name = "logos-derive" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebfe8e1a19049ddbfccbd14ac834b215e11b85b90bab0c2dba7c7b92fb5d5cba" +checksum = "605d9697bcd5ef3a42d38efc51541aa3d6a4a25f7ab6d1ed0da5ac632a26b470" dependencies = [ "logos-codegen", ] @@ -640,9 +631,9 @@ dependencies = [ [[package]] name = "mlua" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de25fc513588ac1273aa8c6dc0fffee6d32c12f38dc75f5cdc74547121a107ef" +checksum = "ab2fea92b2adabd51808311b101551d6e3f8602b65e9fae51f7ad5b3d500f4cd" dependencies = [ "bstr", "either", @@ -659,9 +650,9 @@ dependencies = [ [[package]] name = "mlua-sys" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcdf7c9e260ca82aaa32ac11148941952b856bb8c69aa5a9e65962f21fcb8637" +checksum = "3d4dc9cfc5a7698899802e97480617d9726f7da78c910db989d4d0fd4991d900" dependencies = [ "cc", "cfg-if", @@ -745,7 +736,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -843,9 +834,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -861,9 +852,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -871,9 +862,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -881,18 +872,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.13" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" dependencies = [ "aho-corasick", "memchr", @@ -902,9 +893,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" dependencies = [ "aho-corasick", "memchr", @@ -913,9 +904,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" [[package]] name = "rustc-hash" @@ -934,9 +925,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -1017,9 +1008,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.141" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ "itoa", "memchr", @@ -1097,9 +1088,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.103" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -1108,28 +1099,27 @@ dependencies = [ [[package]] name = "term" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a984c8d058c627faaf5e8e2ed493fa3c51771889196de1016cf9c1c6e90d750" +checksum = "a43bddab41f8626c7bdaab872bbba75f8df5847b516d77c569c746e2ae5eb746" dependencies = [ - "home", - "windows-sys", + "windows-sys 0.60.2", ] [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" dependencies = [ "proc-macro2", "quote", @@ -1157,9 +1147,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.23.2" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1dee9dc43ac2aaf7d3b774e2fba5148212bf2bd9374f4e50152ebe9afd03d42" +checksum = "7211ff1b8f0d3adae1663b7da9ffe396eabe1ca25f0b0bee42b0da29a9ddce93" dependencies = [ "indexmap", "serde", @@ -1172,9 +1162,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97200572db069e74c512a14117b296ba0a80a30123fbbb5aa1f4a348f639ca30" +checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10" dependencies = [ "winnow", ] @@ -1344,20 +1334,35 @@ dependencies = [ [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" dependencies = [ - "windows-sys", + "windows-sys 0.60.2", ] +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", ] [[package]] @@ -1366,14 +1371,31 @@ 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", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -1382,53 +1404,101 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[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_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[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_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[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_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[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_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" -version = "0.7.11" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 37990d0..a393bad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,11 +41,11 @@ crate-type = ["cdylib", "rlib"] [dependencies] # Core serde = "1.0.219" -indexmap = { version = "2.10.0", features = ["serde"] } -logos = "0.15.0" +indexmap = { version = "2.11.0", features = ["serde"] } +logos = "0.15.1" lalrpop-util = { version = "0.22.2", features = ["lexer"] } itoa = "1.0.15" -thiserror = "2.0.12" +thiserror = "2.0.16" # WASM support (optional) wasm-bindgen = { version = "0.2.100", optional = true } @@ -53,7 +53,7 @@ serde-wasm-bindgen = { version = "0.6.5", optional = true } console_error_panic_hook = { version = "0.1.7", optional = true } # Lua support (optional) -mlua = { version = "0.11.1", features = [ +mlua = { version = "0.11.2", features = [ "module", "macros", "serialize", @@ -64,11 +64,11 @@ lalrpop = "0.22.2" [dev-dependencies] wasm-bindgen-test = { version = "0.3.50" } -serde_json = "1.0.141" +serde_json = "1.0.143" serde_norway = "0.9.42" serde_bytes = "0.11.17" -toml_edit = { version = "0.23.2", features = ["serde"] } -anyhow = "1.0.98" +toml_edit = { version = "0.23.4", features = ["serde"] } +anyhow = "1.0.99" paste = "1.0.15" [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] diff --git a/cli/Cargo.toml b/cli/Cargo.toml index e572a81..9aa6aa7 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -14,12 +14,12 @@ documentation = "https://docs.rs/corn-cli" [dependencies] # CLI dependencies -clap = { version = "4.5.41", features = ["derive", "cargo"] } +clap = { version = "4.5.46", features = ["derive", "cargo"] } colored = "3.0.0" # (De)serialization serde = { version = "1.0.219", features = ["derive"] } -serde_json = "1.0.141" +serde_json = "1.0.143" serde_norway = "0.9.42" libcorn = { version = "0.10.0", path = ".." } -toml_edit = { version = "0.23.2", features = ["serde"] } +toml_edit = { version = "0.23.4", features = ["serde"] } From 93740208cb832adc8c6db9bc5f0112869c42bd36 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Fri, 29 Aug 2025 21:53:21 +0200 Subject: [PATCH 60/68] Add test-suite submodule --- .gitmodules | 3 +++ test-suite | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 test-suite diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f6c6716 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "test-suite"] + path = test-suite + url = https://github.com/corn-config/test-suite.git diff --git a/test-suite b/test-suite new file mode 160000 index 0000000..c811ba5 --- /dev/null +++ b/test-suite @@ -0,0 +1 @@ +Subproject commit c811ba5ff67e832811ffdaf1dafc0037f21cc0c7 From 57962835daceff88dc7f4a67b9a123b35fa2c93f Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Fri, 29 Aug 2025 21:53:44 +0200 Subject: [PATCH 61/68] Add no_std support --- Cargo.lock | 26 +++++++++++++++++++++- Cargo.toml | 12 ++++++++--- cli/src/error.rs | 1 - src/ast.rs | 8 +++++-- src/corn.lalrpop | 2 ++ src/de.rs | 51 +++++++++++++++++++++++++++----------------- src/error.rs | 8 +++---- src/lexer.rs | 21 +++++++----------- src/lib.rs | 9 ++++++++ src/value/de.rs | 5 +++-- src/value/integer.rs | 9 ++++---- src/value/mod.rs | 6 ++---- tests/test_suite.rs | 0 13 files changed, 103 insertions(+), 55 deletions(-) create mode 100644 tests/test_suite.rs diff --git a/Cargo.lock b/Cargo.lock index 0761f81..4781223 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "anes" version = "0.1.6" @@ -402,6 +408,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "generic-array" version = "0.14.7" @@ -428,6 +440,17 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "heck" version = "0.5.0" @@ -441,7 +464,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.5", "serde", ] @@ -545,6 +568,7 @@ dependencies = [ "anyhow", "console_error_panic_hook", "criterion", + "hashbrown 0.16.0", "indexmap", "itoa", "lalrpop", diff --git a/Cargo.toml b/Cargo.toml index a393bad..4914920 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,9 @@ documentation = "https://docs.rs/libcorn" readme = "README.md" [features] +default = ["std"] +std = ["serde/std", "indexmap/std", "logos/std"] + # WASM support wasm = [ "dep:wasm-bindgen", @@ -40,12 +43,15 @@ crate-type = ["cdylib", "rlib"] [dependencies] # Core -serde = "1.0.219" -indexmap = { version = "2.11.0", features = ["serde"] } -logos = "0.15.1" +serde = { version = "1.0.219", default-features = false, features = ["alloc"] } +indexmap = { version = "2.11.0", features = [ + "serde", +], default-features = false } +logos = { version = "0.15.1", default-features = false, features = ["export_derive"] } lalrpop-util = { version = "0.22.2", features = ["lexer"] } itoa = "1.0.15" thiserror = "2.0.16" +hashbrown = "0.16.0" # WASM support (optional) wasm-bindgen = { version = "0.2.100", optional = true } diff --git a/cli/src/error.rs b/cli/src/error.rs index 25d1028..8aba108 100644 --- a/cli/src/error.rs +++ b/cli/src/error.rs @@ -21,7 +21,6 @@ impl ExitCode for CornError { fn get_exit_code(&self) -> i32 { match self { CornError::ParseError(_) => 1, - CornError::Io(_) => 3, CornError::InputResolveError(_) => 2, CornError::InvalidSpreadError => 7, CornError::InvalidInterpolationError => 8, diff --git a/src/ast.rs b/src/ast.rs index 9f51a52..20ac713 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,6 +1,10 @@ -use std::collections::HashMap; - use crate::{lexer::StringPart, Integer}; +use alloc::vec::Vec; + +#[cfg(not(feature = "std"))] +use hashbrown::HashMap; +#[cfg(feature = "std")] +use std::collections::HashMap; /// Store for input declarations pub type Inputs<'input> = HashMap<&'input str, Entry<'input>>; diff --git a/src/corn.lalrpop b/src/corn.lalrpop index d441637..d52c4ad 100644 --- a/src/corn.lalrpop +++ b/src/corn.lalrpop @@ -1,6 +1,8 @@ use crate::ast::{Root, Entry, Object, Inputs, PairOrSpread, ChainedKey, EntryOrSpread}; use crate::lexer::{LexicalError, Token, StringPart}; use crate::Integer; +use alloc::vec::Vec; +use alloc::vec; grammar<'input>(input: &'input str); diff --git a/src/de.rs b/src/de.rs index 54577d6..bbbda10 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1,13 +1,16 @@ -use std::borrow::Cow; - -use indexmap::IndexMap; +use alloc::{ + borrow::Cow, + format, + string::{String, ToString}, + vec::Vec, +}; use serde::de::{self, IntoDeserializer}; use crate::{ ast::{Entry, EntryOrSpread, Inputs, PairOrSpread, Root}, lexer::{Lexer, StringPart}, parser::RootParser, - BorrowedObject, BorrowedValue, Error, Result, + BorrowedObject, BorrowedValue, Error, IndexMap, Result, }; /// A structure that deserializes Corn configuration values. @@ -77,7 +80,7 @@ impl<'de> Deserializer<'de> { Entry::Float(float) => Ok(BorrowedValue::Float(*float)), Entry::Boolean(boolean) => Ok(BorrowedValue::Boolean(*boolean)), Entry::Object(obj) => { - let mut resolved_object = IndexMap::new(); + let mut resolved_object = IndexMap::default(); for pair_or_spread in &obj.pairs { match pair_or_spread { @@ -165,7 +168,7 @@ impl<'de> Deserializer<'de> { let (first, rest) = path.split_first().expect("Internal splitting error"); let entry = obj .entry(first.clone()) - .or_insert_with(|| BorrowedValue::Object(IndexMap::new())); + .or_insert_with(|| BorrowedValue::Object(IndexMap::default())); match entry { BorrowedValue::Object(nested_obj) => { @@ -243,6 +246,7 @@ impl<'de> Deserializer<'de> { input: &str, inputs: &Inputs<'input>, ) -> Result> { + #[cfg(feature = "std")] if let Some(env) = input.strip_prefix("env_") { if let Ok(env) = std::env::var(env) { return Ok(BorrowedValue::String(Cow::Owned(env))); @@ -299,13 +303,13 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { BorrowedValue::Null => visitor.visit_unit(), BorrowedValue::Array(ref mut items) => { let mut seq = Vec::new(); - std::mem::swap(items, &mut seq); + core::mem::swap(items, &mut seq); visitor.visit_seq(SeqAccess::new(seq)) } BorrowedValue::Object(ref mut object) => { - let mut map = IndexMap::new(); - std::mem::swap(object, &mut map); + let mut map = IndexMap::default(); + core::mem::swap(object, &mut map); visitor.visit_map(MapAccess::new(map)) } @@ -441,7 +445,7 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { match self.value { BorrowedValue::Array(ref mut items) => { let mut seq = Vec::new(); - std::mem::swap(items, &mut seq); + core::mem::swap(items, &mut seq); visitor.visit_seq(SeqAccess::new(seq)) } @@ -474,8 +478,8 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { { match self.value { BorrowedValue::Object(ref mut object) => { - let mut map = IndexMap::new(); - std::mem::swap(object, &mut map); + let mut map = IndexMap::default(); + core::mem::swap(object, &mut map); visitor.visit_map(MapAccess::new(map)) } @@ -509,8 +513,8 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { visitor.visit_enum(string.as_ref().into_deserializer()) } BorrowedValue::Object(ref mut object) => { - let mut map = IndexMap::new(); - std::mem::swap(object, &mut map); + let mut map = IndexMap::default(); + core::mem::swap(object, &mut map); visitor.visit_enum(EnumAccess::new(map)) } @@ -534,7 +538,7 @@ impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { } struct SeqAccess<'de> { - items: std::vec::IntoIter>, + items: alloc::vec::IntoIter>, } impl<'de> SeqAccess<'de> { @@ -622,7 +626,10 @@ impl<'de> de::EnumAccess<'de> for EnumAccess<'de> { type Error = Error; type Variant = VariantAccess<'de>; - fn variant_seed(self, seed: V) -> std::result::Result<(V::Value, Self::Variant), Self::Error> + fn variant_seed( + self, + seed: V, + ) -> core::result::Result<(V::Value, Self::Variant), Self::Error> where V: de::DeserializeSeed<'de>, { @@ -659,21 +666,25 @@ impl<'de> VariantAccess<'de> { impl<'de> de::VariantAccess<'de> for VariantAccess<'de> { type Error = Error; - fn unit_variant(self) -> std::result::Result<(), Self::Error> { + fn unit_variant(self) -> core::result::Result<(), Self::Error> { match self.value { BorrowedValue::Null => Ok(()), ref value => Err(value.invalid_type("unit variant (null)")), } } - fn newtype_variant_seed(self, seed: T) -> std::result::Result + fn newtype_variant_seed(self, seed: T) -> core::result::Result where T: de::DeserializeSeed<'de>, { seed.deserialize(&mut Deserializer::with_value(self.value)) } - fn tuple_variant(self, _len: usize, visitor: V) -> std::result::Result + fn tuple_variant( + self, + _len: usize, + visitor: V, + ) -> core::result::Result where V: de::Visitor<'de>, { @@ -687,7 +698,7 @@ impl<'de> de::VariantAccess<'de> for VariantAccess<'de> { self, _fields: &'static [&'static str], visitor: V, - ) -> std::result::Result + ) -> core::result::Result where V: de::Visitor<'de>, { diff --git a/src/error.rs b/src/error.rs index c34b70b..a5ff4fa 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,13 +1,11 @@ -use std::fmt::Display; +use alloc::string::{String, ToString}; +use core::fmt::Display; use thiserror::Error; -pub type Result = std::result::Result; +pub type Result = core::result::Result; #[derive(Error, Debug)] pub enum Error { - #[error(transparent)] - Io(#[from] std::io::Error), - #[error("failed to resolve referenced input `{0}`")] InputResolveError(String), diff --git a/src/lexer.rs b/src/lexer.rs index 0e602ce..0cbbe63 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -1,12 +1,7 @@ -use std::{ - borrow::Cow, - fmt, - num::{ParseFloatError, ParseIntError}, - str::FromStr, -}; -use thiserror::Error; - +use alloc::{borrow::Cow, string::String, vec::Vec}; +use core::{num::ParseIntError, str::FromStr}; use logos::{Logos, SpannedIter}; +use thiserror::Error; use crate::Integer; @@ -40,7 +35,7 @@ pub enum LexicalError { #[error("Integer parsing error: {0}")] InvalidInteger(#[from] ParseIntError), #[error("Float parsing error: {0}")] - InvalidFloat(#[from] ParseFloatError), + InvalidFloat(#[from] core::num::ParseFloatError), #[default] #[error("Encountered invalid token")] InvalidToken, @@ -183,7 +178,7 @@ fn parse_literal<'input>( StringContext::Content => current_literal.push_str(string_lex.slice()), StringContext::Interpolation(input) => { if !current_literal.is_empty() { - parts.push(StringPart::Literal(Cow::Owned(std::mem::take( + parts.push(StringPart::Literal(Cow::Owned(core::mem::take( &mut current_literal, )))); } @@ -233,7 +228,7 @@ fn parse_literal<'input>( } if !current_literal.is_empty() { - parts.push(StringPart::Literal(Cow::Owned(std::mem::take( + parts.push(StringPart::Literal(Cow::Owned(core::mem::take( &mut current_literal, )))); } @@ -243,8 +238,8 @@ fn parse_literal<'input>( Some(parts) } -impl fmt::Display for Token<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Display for Token<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { Self::Let => write!(f, "let"), Self::In => write!(f, "in"), diff --git a/src/lib.rs b/src/lib.rs index 4affd20..4718f3f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,12 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; + +#[cfg(feature = "std")] +pub(crate) use indexmap::IndexMap; +#[cfg(not(feature = "std"))] +pub(crate) type IndexMap = indexmap::IndexMap; + mod de; #[cfg(any( feature = "lua51", diff --git a/src/value/de.rs b/src/value/de.rs index 5b80b29..886a102 100644 --- a/src/value/de.rs +++ b/src/value/de.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use serde::{de::Visitor, Deserialize}; use crate::{Object, Value}; @@ -12,7 +13,7 @@ impl<'de> Deserialize<'de> for Value { impl<'de> Visitor<'de> for ValueVisitor { type Value = Value; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { formatter.write_str("any valid Corn value") } @@ -99,7 +100,7 @@ impl<'de> Deserialize<'de> for Value { where A: serde::de::MapAccess<'de>, { - let mut dict = Object::new(); + let mut dict = Object::default(); while let Some((key, value)) = map.next_entry()? { dict.insert(key, value); diff --git a/src/value/integer.rs b/src/value/integer.rs index 7f38c67..123c233 100644 --- a/src/value/integer.rs +++ b/src/value/integer.rs @@ -1,8 +1,9 @@ +use core::fmt::{Debug, Display}; + use serde::{ de::{self, Visitor}, forward_to_deserialize_any, Deserialize, Serialize, }; -use std::fmt::{self, Debug, Display}; use crate::Error; @@ -13,13 +14,13 @@ pub struct Integer { } impl Debug for Integer { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "Integer({self})") } } impl Display for Integer { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self.inner { IntegerType::Signed(n) => f.write_str(itoa::Buffer::new().format(n)), IntegerType::Unsigned(n) => f.write_str(itoa::Buffer::new().format(n)), @@ -104,7 +105,7 @@ impl<'de> Deserialize<'de> for Integer { impl<'de> Visitor<'de> for IntegerVisitor { type Value = Integer; - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { formatter.write_str("an Integer") } diff --git a/src/value/mod.rs b/src/value/mod.rs index ba0a051..b4500e9 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -1,6 +1,4 @@ -use std::borrow::Cow; - -use indexmap::IndexMap; +use alloc::{borrow::Cow, format, string::String, vec::Vec}; mod de; mod integer; @@ -8,7 +6,7 @@ mod ser; pub use integer::Integer; -use crate::Error; +use crate::{Error, IndexMap}; /// Object: Key-value collection that preserves insertion order pub type Object = IndexMap; diff --git a/tests/test_suite.rs b/tests/test_suite.rs new file mode 100644 index 0000000..e69de29 From 5a1d8d05227cba2cac3271587194be5866f4c30b Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Fri, 29 Aug 2025 21:58:11 +0200 Subject: [PATCH 62/68] Make clippy happy --- src/de.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/de.rs b/src/de.rs index bbbda10..d9fe3d5 100644 --- a/src/de.rs +++ b/src/de.rs @@ -20,13 +20,13 @@ pub struct Deserializer<'de> { } /// Parse a Corn configuration string into a borrowed value. -pub fn parse(input: &str) -> Result { +pub fn parse(input: &str) -> Result> { Deserializer::parse(input) } impl<'de> Deserializer<'de> { /// Parse a Corn configuration string into a borrowed value. - pub fn parse(input: &str) -> Result { + pub fn parse(input: &str) -> Result> { let mut lexer = Lexer::new(input); let parser = RootParser::new(); let Root { inputs, object } = parser @@ -85,7 +85,7 @@ impl<'de> Deserializer<'de> { for pair_or_spread in &obj.pairs { match pair_or_spread { PairOrSpread::Pair(key, value) => { - fn unescape_key(key: &str) -> Cow { + fn unescape_key(key: &str) -> Cow<'_, str> { if key.contains("\\'") { Cow::Owned(key.replace("\\'", "'")) } else { From 2f40ed750be58d98674ec9c31136b99104c7b018 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Fri, 29 Aug 2025 22:24:21 +0200 Subject: [PATCH 63/68] Updgrade to edition 2024 --- Cargo.toml | 2 +- cli/Cargo.toml | 2 +- cli/src/main.rs | 4 ++-- src/ast.rs | 2 +- src/de.rs | 10 +++++----- src/lexer.rs | 10 +++++----- src/lib.rs | 2 +- src/value/de.rs | 2 +- src/value/integer.rs | 3 ++- src/wasm.rs | 2 +- tests/test_suite.rs | 0 11 files changed, 20 insertions(+), 19 deletions(-) delete mode 100644 tests/test_suite.rs diff --git a/Cargo.toml b/Cargo.toml index 4914920..c5cc215 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ members = ["cli"] [package] name = "libcorn" version = "0.10.0" -edition = "2021" +edition = "2024" license = "MIT" description = "Parsing engine for Corn, a simple and pain-free configuration language." repository = "https://github.com/JakeStanger/corn" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 9aa6aa7..230096a 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "corn-cli" version = "0.10.0" -edition = "2021" +edition = "2024" license = "MIT" description = "CLI for Corn. A simple and pain-free configuration language." repository = "https://github.com/corn-config/corn" diff --git a/cli/src/main.rs b/cli/src/main.rs index 53cdb5f..d240d8e 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,4 +1,4 @@ -use corn::{parse, BorrowedValue}; +use corn::{BorrowedValue, parse}; use std::io::Read; use std::process::exit; use std::{fs, io}; @@ -7,7 +7,7 @@ use clap::{Parser, ValueEnum}; use colored::Colorize; mod error; -use error::{print_err, Error, ExitCode}; +use error::{Error, ExitCode, print_err}; #[derive(ValueEnum, Clone, Copy, Debug)] enum OutputType { diff --git a/src/ast.rs b/src/ast.rs index 20ac713..035919a 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,4 +1,4 @@ -use crate::{lexer::StringPart, Integer}; +use crate::{Integer, lexer::StringPart}; use alloc::vec::Vec; #[cfg(not(feature = "std"))] diff --git a/src/de.rs b/src/de.rs index d9fe3d5..dce3b83 100644 --- a/src/de.rs +++ b/src/de.rs @@ -7,10 +7,10 @@ use alloc::{ use serde::de::{self, IntoDeserializer}; use crate::{ + BorrowedObject, BorrowedValue, Error, IndexMap, Result, ast::{Entry, EntryOrSpread, Inputs, PairOrSpread, Root}, lexer::{Lexer, StringPart}, parser::RootParser, - BorrowedObject, BorrowedValue, Error, IndexMap, Result, }; /// A structure that deserializes Corn configuration values. @@ -247,10 +247,10 @@ impl<'de> Deserializer<'de> { inputs: &Inputs<'input>, ) -> Result> { #[cfg(feature = "std")] - if let Some(env) = input.strip_prefix("env_") { - if let Ok(env) = std::env::var(env) { - return Ok(BorrowedValue::String(Cow::Owned(env))); - } + if let Some(env) = input.strip_prefix("env_") + && let Ok(env) = std::env::var(env) + { + return Ok(BorrowedValue::String(Cow::Owned(env))); } if let Some(entry) = inputs.get(input) { diff --git a/src/lexer.rs b/src/lexer.rs index 0cbbe63..1f83419 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -215,11 +215,11 @@ fn parse_literal<'input>( let slice = string_lex.slice(); let hex_part = &slice[3..slice.len() - 1]; - if let Ok(code) = u32::from_str_radix(hex_part, 16) { - if let Some(unicode_char) = char::from_u32(code) { - current_literal.push(unicode_char); - continue; - } + if let Ok(code) = u32::from_str_radix(hex_part, 16) + && let Some(unicode_char) = char::from_u32(code) + { + current_literal.push(unicode_char); + continue; } current_literal.push('\u{FFFD}'); diff --git a/src/lib.rs b/src/lib.rs index 4718f3f..163f8c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,6 @@ pub mod ast; pub mod lexer; lalrpop_util::lalrpop_mod!(pub parser, "/corn.rs"); -pub use de::{from_str, parse, Deserializer}; +pub use de::{Deserializer, from_str, parse}; pub use error::{Error, Result}; pub use value::{BorrowedObject, BorrowedValue, Integer, Object, Value}; diff --git a/src/value/de.rs b/src/value/de.rs index 886a102..ae66733 100644 --- a/src/value/de.rs +++ b/src/value/de.rs @@ -1,5 +1,5 @@ use alloc::{string::String, vec::Vec}; -use serde::{de::Visitor, Deserialize}; +use serde::{Deserialize, de::Visitor}; use crate::{Object, Value}; diff --git a/src/value/integer.rs b/src/value/integer.rs index 123c233..978ce0a 100644 --- a/src/value/integer.rs +++ b/src/value/integer.rs @@ -1,8 +1,9 @@ use core::fmt::{Debug, Display}; use serde::{ + Deserialize, Serialize, de::{self, Visitor}, - forward_to_deserialize_any, Deserialize, Serialize, + forward_to_deserialize_any, }; use crate::Error; diff --git a/src/wasm.rs b/src/wasm.rs index b688bbf..863f226 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -1,8 +1,8 @@ #![allow(dead_code)] use serde_wasm_bindgen::to_value; -use wasm_bindgen::prelude::*; use wasm_bindgen::JsValue; +use wasm_bindgen::prelude::*; #[cfg(test)] use wasm_bindgen_test::*; diff --git a/tests/test_suite.rs b/tests/test_suite.rs deleted file mode 100644 index e69de29..0000000 From 6f64b83f0f4d051689c7f59d041e4eebc0c475b4 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Wed, 24 Sep 2025 19:22:56 +0200 Subject: [PATCH 64/68] Switch from serde to serde_core --- Cargo.lock | 196 +++++++++++++++++++++++++------------------ Cargo.toml | 27 +++--- src/de.rs | 2 +- src/error.rs | 2 +- src/value/de.rs | 26 +++--- src/value/integer.rs | 4 +- src/value/ser.rs | 10 +-- 7 files changed, 152 insertions(+), 115 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4781223..890b766 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,9 +75,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "ascii-canvas" @@ -117,9 +117,9 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" -version = "2.9.3" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" [[package]] name = "block-buffer" @@ -154,10 +154,11 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.34" +version = "1.2.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" +checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9" dependencies = [ + "find-msvc-tools", "shlex", ] @@ -196,9 +197,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.46" +version = "4.5.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" +checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" dependencies = [ "clap_builder", "clap_derive", @@ -206,9 +207,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.46" +version = "4.5.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" +checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" dependencies = [ "anstream", "anstyle", @@ -218,9 +219,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.45" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" +checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" dependencies = [ "heck", "proc-macro2", @@ -388,14 +389,21 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" +checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b" dependencies = [ "serde", + "serde_core", "typeid", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" + [[package]] name = "fixedbitset" version = "0.5.7" @@ -434,12 +442,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" - [[package]] name = "hashbrown" version = "0.16.0" @@ -459,13 +461,14 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "indexmap" -version = "2.11.0" +version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown", "serde", + "serde_core", ] [[package]] @@ -500,9 +503,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" dependencies = [ "once_cell", "wasm-bindgen", @@ -557,9 +560,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.175" +version = "0.2.176" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174" [[package]] name = "libcorn" @@ -568,7 +571,7 @@ dependencies = [ "anyhow", "console_error_panic_hook", "criterion", - "hashbrown 0.16.0", + "hashbrown", "indexmap", "itoa", "lalrpop", @@ -579,6 +582,7 @@ dependencies = [ "serde", "serde-wasm-bindgen", "serde_bytes", + "serde_core", "serde_json", "serde_norway", "thiserror", @@ -599,9 +603,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "logos" @@ -655,9 +659,9 @@ dependencies = [ [[package]] name = "mlua" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2fea92b2adabd51808311b101551d6e3f8602b65e9fae51f7ad5b3d500f4cd" +checksum = "5b3dd94c3c4dea0049b22296397040840a8f6b5b5229f438434ba82df402b42d" dependencies = [ "bstr", "either", @@ -976,16 +980,17 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.226" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" dependencies = [ + "serde_core", "serde_derive", ] @@ -1012,18 +1017,28 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.17" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" dependencies = [ "serde", + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.226" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" +dependencies = [ + "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.226" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" dependencies = [ "proc-macro2", "quote", @@ -1032,14 +1047,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -1057,11 +1073,11 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" +checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -1123,11 +1139,11 @@ dependencies = [ [[package]] name = "term" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a43bddab41f8626c7bdaab872bbba75f8df5847b516d77c569c746e2ae5eb746" +checksum = "2111ef44dae28680ae9752bb89409e7310ca33a8c621ebe7b106cf5c928b3ac0" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.0", ] [[package]] @@ -1162,21 +1178,21 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" +checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1" dependencies = [ - "serde", + "serde_core", ] [[package]] name = "toml_edit" -version = "0.23.4" +version = "0.23.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7211ff1b8f0d3adae1663b7da9ffe396eabe1ca25f0b0bee42b0da29a9ddce93" +checksum = "f3effe7c0e86fdff4f69cdd2ccc1b96f933e24811c5441d44904e8683e27184b" dependencies = [ "indexmap", - "serde", + "serde_core", "serde_spanned", "toml_datetime", "toml_parser", @@ -1186,18 +1202,18 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10" +checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627" dependencies = [ "winnow", ] [[package]] name = "toml_writer" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64" +checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109" [[package]] name = "typeid" @@ -1213,9 +1229,9 @@ checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" [[package]] name = "unicode-xid" @@ -1253,21 +1269,22 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" dependencies = [ "bumpalo", "log", @@ -1279,9 +1296,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" dependencies = [ "cfg-if", "js-sys", @@ -1292,9 +1309,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1302,9 +1319,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" dependencies = [ "proc-macro2", "quote", @@ -1315,18 +1332,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-bindgen-test" -version = "0.3.50" +version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66c8d5e33ca3b6d9fa3b4676d774c5778031d27a578c2b007f905acf816152c3" +checksum = "4e381134e148c1062f965a42ed1f5ee933eef2927c3f70d1812158f711d39865" dependencies = [ "js-sys", "minicov", @@ -1337,9 +1354,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.50" +version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b" +checksum = "b673bca3298fe582aeef8352330ecbad91849f85090805582400850f8270a2e8" dependencies = [ "proc-macro2", "quote", @@ -1348,9 +1365,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" dependencies = [ "js-sys", "wasm-bindgen", @@ -1358,11 +1375,11 @@ dependencies = [ [[package]] name = "winapi-util" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.0", ] [[package]] @@ -1371,6 +1388,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + [[package]] name = "windows-sys" version = "0.59.0" @@ -1389,6 +1412,15 @@ dependencies = [ "windows-targets 0.53.3", ] +[[package]] +name = "windows-sys" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +dependencies = [ + "windows-link 0.2.0", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -1411,7 +1443,7 @@ version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ - "windows-link", + "windows-link 0.1.3", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", diff --git a/Cargo.toml b/Cargo.toml index c5cc215..304d3a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ readme = "README.md" [features] default = ["std"] -std = ["serde/std", "indexmap/std", "logos/std"] +std = ["serde_core/std", "indexmap/std", "logos/std"] # WASM support wasm = [ @@ -43,23 +43,27 @@ crate-type = ["cdylib", "rlib"] [dependencies] # Core -serde = { version = "1.0.219", default-features = false, features = ["alloc"] } -indexmap = { version = "2.11.0", features = [ +serde_core = { version = "1.0.226", default-features = false, features = [ + "alloc", +] } +indexmap = { version = "2.11.4", features = [ "serde", ], default-features = false } -logos = { version = "0.15.1", default-features = false, features = ["export_derive"] } +logos = { version = "0.15.1", default-features = false, features = [ + "export_derive", +] } lalrpop-util = { version = "0.22.2", features = ["lexer"] } itoa = "1.0.15" thiserror = "2.0.16" hashbrown = "0.16.0" # WASM support (optional) -wasm-bindgen = { version = "0.2.100", optional = true } +wasm-bindgen = { version = "0.2.104", optional = true } serde-wasm-bindgen = { version = "0.6.5", optional = true } console_error_panic_hook = { version = "0.1.7", optional = true } # Lua support (optional) -mlua = { version = "0.11.2", features = [ +mlua = { version = "0.11.3", features = [ "module", "macros", "serialize", @@ -69,13 +73,14 @@ mlua = { version = "0.11.2", features = [ lalrpop = "0.22.2" [dev-dependencies] -wasm-bindgen-test = { version = "0.3.50" } -serde_json = "1.0.143" +wasm-bindgen-test = { version = "0.3.54" } +serde_json = "1.0.145" serde_norway = "0.9.42" -serde_bytes = "0.11.17" -toml_edit = { version = "0.23.4", features = ["serde"] } -anyhow = "1.0.99" +serde_bytes = "0.11.19" +toml_edit = { version = "0.23.6", features = ["serde"] } +anyhow = "1.0.100" paste = "1.0.15" +serde = { version = "1.0.226", features = ["derive"] } [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] criterion = { version = "0.7.0", features = ["html_reports"] } diff --git a/src/de.rs b/src/de.rs index dce3b83..a9b2302 100644 --- a/src/de.rs +++ b/src/de.rs @@ -4,7 +4,7 @@ use alloc::{ string::{String, ToString}, vec::Vec, }; -use serde::de::{self, IntoDeserializer}; +use serde_core::de::{self, IntoDeserializer}; use crate::{ BorrowedObject, BorrowedValue, Error, IndexMap, Result, diff --git a/src/error.rs b/src/error.rs index a5ff4fa..a7e09ce 100644 --- a/src/error.rs +++ b/src/error.rs @@ -22,7 +22,7 @@ pub enum Error { ParseError(String), } -impl serde::de::Error for Error { +impl serde_core::de::Error for Error { fn custom(msg: T) -> Self where T: Display, diff --git a/src/value/de.rs b/src/value/de.rs index ae66733..d2a2c7b 100644 --- a/src/value/de.rs +++ b/src/value/de.rs @@ -1,12 +1,12 @@ use alloc::{string::String, vec::Vec}; -use serde::{Deserialize, de::Visitor}; +use serde_core::{Deserialize, de::Visitor}; use crate::{Object, Value}; impl<'de> Deserialize<'de> for Value { fn deserialize(deserializer: D) -> Result where - D: serde::Deserializer<'de>, + D: serde_core::Deserializer<'de>, { struct ValueVisitor; @@ -20,7 +20,7 @@ impl<'de> Deserialize<'de> for Value { #[inline] fn visit_bool(self, v: bool) -> Result where - E: serde::de::Error, + E: serde_core::de::Error, { Ok(Value::Boolean(v)) } @@ -28,7 +28,7 @@ impl<'de> Deserialize<'de> for Value { #[inline] fn visit_i64(self, v: i64) -> Result where - E: serde::de::Error, + E: serde_core::de::Error, { Ok(Value::Integer(v.into())) } @@ -36,56 +36,56 @@ impl<'de> Deserialize<'de> for Value { #[inline] fn visit_u64(self, v: u64) -> Result where - E: serde::de::Error, + E: serde_core::de::Error, { Ok(Value::Integer(v.into())) } fn visit_f64(self, v: f64) -> Result where - E: serde::de::Error, + E: serde_core::de::Error, { Ok(Value::Float(v)) } fn visit_str(self, v: &str) -> Result where - E: serde::de::Error, + E: serde_core::de::Error, { self.visit_string(String::from(v)) } fn visit_string(self, v: String) -> Result where - E: serde::de::Error, + E: serde_core::de::Error, { Ok(Value::String(v)) } fn visit_none(self) -> Result where - E: serde::de::Error, + E: serde_core::de::Error, { Ok(Value::Null) } fn visit_some(self, deserializer: D) -> Result where - D: serde::Deserializer<'de>, + D: serde_core::Deserializer<'de>, { Deserialize::deserialize(deserializer) } fn visit_unit(self) -> Result where - E: serde::de::Error, + E: serde_core::de::Error, { Ok(Value::Null) } fn visit_seq(self, mut seq: A) -> Result where - A: serde::de::SeqAccess<'de>, + A: serde_core::de::SeqAccess<'de>, { let mut vec = Vec::new(); @@ -98,7 +98,7 @@ impl<'de> Deserialize<'de> for Value { fn visit_map(self, mut map: A) -> Result where - A: serde::de::MapAccess<'de>, + A: serde_core::de::MapAccess<'de>, { let mut dict = Object::default(); diff --git a/src/value/integer.rs b/src/value/integer.rs index 978ce0a..89ccd6a 100644 --- a/src/value/integer.rs +++ b/src/value/integer.rs @@ -1,6 +1,6 @@ use core::fmt::{Debug, Display}; -use serde::{ +use serde_core::{ Deserialize, Serialize, de::{self, Visitor}, forward_to_deserialize_any, @@ -87,7 +87,7 @@ impl Integer { impl Serialize for Integer { fn serialize(&self, serializer: S) -> Result where - S: serde::Serializer, + S: serde_core::Serializer, { match self.inner { IntegerType::Signed(integer) => serializer.serialize_i64(integer), diff --git a/src/value/ser.rs b/src/value/ser.rs index aee31cc..8e1ed0d 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -1,4 +1,4 @@ -use serde::Serialize; +use serde_core::Serialize; use crate::{BorrowedValue, Value}; @@ -6,7 +6,7 @@ impl Serialize for Value { #[inline] fn serialize(&self, serializer: S) -> Result where - S: serde::Serializer, + S: serde_core::Serializer, { match self { Self::String(s) => serializer.serialize_str(s), @@ -14,7 +14,7 @@ impl Serialize for Value { Self::Float(f) => f.serialize(serializer), Self::Boolean(v) => serializer.serialize_bool(*v), Self::Object(obj) => { - use serde::ser::SerializeMap; + use serde_core::ser::SerializeMap; let mut map = serializer.serialize_map(Some(obj.len()))?; for (k, v) in obj { @@ -33,7 +33,7 @@ impl Serialize for BorrowedValue<'_> { #[inline] fn serialize(&self, serializer: S) -> Result where - S: serde::Serializer, + S: serde_core::Serializer, { match self { Self::String(s) => serializer.serialize_str(s), @@ -41,7 +41,7 @@ impl Serialize for BorrowedValue<'_> { Self::Float(f) => f.serialize(serializer), Self::Boolean(v) => serializer.serialize_bool(*v), Self::Object(obj) => { - use serde::ser::SerializeMap; + use serde_core::ser::SerializeMap; let mut map = serializer.serialize_map(Some(obj.len()))?; for (k, v) in obj { From 2b04b0b2839103f3f0d95943c93444073c545bec Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Wed, 24 Dec 2025 10:40:46 +0100 Subject: [PATCH 65/68] Update test-suite --- test-suite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-suite b/test-suite index c811ba5..1e2662b 160000 --- a/test-suite +++ b/test-suite @@ -1 +1 @@ -Subproject commit c811ba5ff67e832811ffdaf1dafc0037f21cc0c7 +Subproject commit 1e2662bfec18e6a4c1ef495995ac915defa55f02 From bc9b534bb1f21e782cf6c0d04e7a88037531e237 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Wed, 24 Dec 2025 10:47:08 +0100 Subject: [PATCH 66/68] Update dependencies --- Cargo.lock | 519 ++++++++++++++++++++++++----------------------- Cargo.toml | 26 +-- benches/serde.rs | 2 +- 3 files changed, 276 insertions(+), 271 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 890b766..553a8d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,13 +4,22 @@ version = 4 [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] +[[package]] +name = "alloca" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4" +dependencies = [ + "cc", +] + [[package]] name = "allocator-api2" version = "0.2.21" @@ -25,9 +34,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.20" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -40,9 +49,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" @@ -55,22 +64,22 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.10" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -88,6 +97,17 @@ dependencies = [ "term", ] +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -117,9 +137,9 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" -version = "2.9.4" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "block-buffer" @@ -132,9 +152,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ "memchr", "serde", @@ -142,9 +162,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "cast" @@ -154,9 +174,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.38" +version = "1.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9" +checksum = "9f50d563227a1c37cc0a263f64eca3334388c01c5e4c4861a9def205c614383c" dependencies = [ "find-msvc-tools", "shlex", @@ -164,9 +184,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "ciborium" @@ -197,9 +217,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.48" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" +checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" dependencies = [ "clap_builder", "clap_derive", @@ -207,9 +227,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.48" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" +checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" dependencies = [ "anstream", "anstyle", @@ -219,9 +239,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.47" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", @@ -231,9 +251,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "colorchoice" @@ -284,10 +304,11 @@ dependencies = [ [[package]] name = "criterion" -version = "0.7.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" +checksum = "4d883447757bb0ee46f233e9dc22eb84d93a9508c9b868687b274fc431d886bf" dependencies = [ + "alloca", "anes", "cast", "ciborium", @@ -296,6 +317,7 @@ dependencies = [ "itertools 0.13.0", "num-traits", "oorandom", + "page_size", "plotters", "rayon", "regex", @@ -307,9 +329,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.6.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" +checksum = "ed943f81ea2faa8dcecbbfa50164acf95d555afec96a27871663b300e387b2e4" dependencies = [ "cast", "itertools 0.13.0", @@ -348,9 +370,9 @@ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -389,9 +411,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b" +checksum = "89e8918065695684b2b0702da20382d5ae6065cf3327bc2d6436bd49a71ce9f3" dependencies = [ "serde", "serde_core", @@ -400,9 +422,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" [[package]] name = "fixedbitset" @@ -434,19 +456,20 @@ dependencies = [ [[package]] name = "half" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", + "zerocopy", ] [[package]] name = "hashbrown" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", @@ -461,9 +484,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "indexmap" -version = "2.11.4" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", "hashbrown", @@ -473,9 +496,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -497,15 +520,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "7ee5b5339afb4c41626dde77b7a611bd4f2c202b897852b4bcf5d03eddc61010" [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", @@ -552,17 +575,11 @@ dependencies = [ "rustversion", ] -[[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.176" +version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" [[package]] name = "libcorn" @@ -591,42 +608,47 @@ dependencies = [ "wasm-bindgen-test", ] +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "logos" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff472f899b4ec2d99161c51f60ff7075eeb3097069a36050d8037a6325eb8154" +checksum = "a790d11254054e5dc83902dba85d253ff06ceb0cfafb12be8773435cb9dfb4f4" dependencies = [ "logos-derive", ] [[package]] name = "logos-codegen" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "192a3a2b90b0c05b27a0b2c43eecdb7c415e29243acc3f89cc8247a5b693045c" +checksum = "f60337c43a38313b58871f8d5d76872b8e17aa9d51fad494b5e76092c0ce05f5" dependencies = [ "beef", "fnv", - "lazy_static", "proc-macro2", "quote", + "regex-automata", "regex-syntax", "rustc_version", "syn", @@ -634,24 +656,24 @@ dependencies = [ [[package]] name = "logos-derive" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605d9697bcd5ef3a42d38efc51541aa3d6a4a25f7ab6d1ed0da5ac632a26b470" +checksum = "d151b2ae667f69e10b8738f5cac0c746faa22b2e15ea7e83b55476afec3767dc" dependencies = [ "logos-codegen", ] [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "minicov" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" +checksum = "4869b6a491569605d66d3952bcdf03df789e5b536e5f0cf7758a7f08a55ae24d" dependencies = [ "cc", "walkdir", @@ -659,13 +681,14 @@ dependencies = [ [[package]] name = "mlua" -version = "0.11.3" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b3dd94c3c4dea0049b22296397040840a8f6b5b5229f438434ba82df402b42d" +checksum = "935ac67539907efcd7198137eb7358e052555f77fe1b2916600a2249351f2b33" dependencies = [ "bstr", "either", "erased-serde", + "libc", "mlua-sys", "mlua_derive", "num-traits", @@ -678,9 +701,9 @@ dependencies = [ [[package]] name = "mlua-sys" -version = "0.8.3" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d4dc9cfc5a7698899802e97480617d9726f7da78c910db989d4d0fd4991d900" +checksum = "8c968af21bf6b19fc9ca8e7b85ee16f86e4c9e3d0591de101a5608086bda0ad8" dependencies = [ "cc", "cfg-if", @@ -708,6 +731,15 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -715,6 +747,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -725,9 +758,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "oorandom" @@ -744,11 +777,21 @@ dependencies = [ "num-traits", ] +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -756,15 +799,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -862,18 +905,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -900,18 +943,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.11.2" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -921,9 +964,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -932,9 +975,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "rustc-hash" @@ -959,9 +1002,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea" [[package]] name = "same-file" @@ -986,9 +1029,9 @@ checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.226" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", @@ -1027,18 +1070,18 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.226" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.226" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -1047,15 +1090,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "6af14725505314343e673e9ecb7cd7e8a36aa9791eb936235a3567cc31447ae4" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -1073,9 +1116,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee" +checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" dependencies = [ "serde_core", ] @@ -1128,9 +1171,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.106" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", @@ -1139,27 +1182,27 @@ dependencies = [ [[package]] name = "term" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2111ef44dae28680ae9752bb89409e7310ca33a8c621ebe7b106cf5c928b3ac0" +checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1" dependencies = [ - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] name = "thiserror" -version = "2.0.16" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.16" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", @@ -1178,18 +1221,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.2" +version = "0.7.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" dependencies = [ "serde_core", ] [[package]] name = "toml_edit" -version = "0.23.6" +version = "0.23.10+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3effe7c0e86fdff4f69cdd2ccc1b96f933e24811c5441d44904e8683e27184b" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ "indexmap", "serde_core", @@ -1202,18 +1245,18 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.3" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627" +checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" dependencies = [ "winnow", ] [[package]] name = "toml_writer" -version = "1.0.3" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109" +checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" [[package]] name = "typeid" @@ -1223,15 +1266,15 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.19" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-xid" @@ -1269,9 +1312,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", "once_cell", @@ -1280,25 +1323,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-futures" -version = "0.4.54" +version = "0.4.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" dependencies = [ "cfg-if", "js-sys", @@ -1309,9 +1338,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1319,34 +1348,42 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-bindgen-test" -version = "0.3.54" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e381134e148c1062f965a42ed1f5ee933eef2927c3f70d1812158f711d39865" +checksum = "25e90e66d265d3a1efc0e72a54809ab90b9c0c515915c67cdf658689d2c22c6c" dependencies = [ + "async-trait", + "cast", "js-sys", + "libm", "minicov", + "nu-ansi-term", + "num-traits", + "oorandom", + "serde", + "serde_json", "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test-macro", @@ -1354,9 +1391,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.54" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b673bca3298fe582aeef8352330ecbad91849f85090805582400850f8270a2e8" +checksum = "7150335716dce6028bead2b848e72f47b45e7b9422f64cccdc23bedca89affc1" dependencies = [ "proc-macro2", "quote", @@ -1365,34 +1402,50 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.81" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" dependencies = [ "js-sys", "wasm-bindgen", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] -name = "windows-link" -version = "0.1.3" +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-link" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" @@ -1400,25 +1453,16 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.3", + "windows-targets", ] [[package]] name = "windows-sys" -version = "0.61.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.0", + "windows-link", ] [[package]] @@ -1427,31 +1471,14 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" -dependencies = [ - "windows-link 0.1.3", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "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]] @@ -1460,84 +1487,42 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - [[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_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[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_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - [[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_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - [[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_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -1545,16 +1530,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" +name = "winnow" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +dependencies = [ + "memchr", +] [[package]] -name = "winnow" -version = "0.7.13" +name = "zerocopy" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" dependencies = [ - "memchr", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] + +[[package]] +name = "zmij" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e404bcd8afdaf006e529269d3e85a743f9480c3cef60034d77860d02964f3ba" diff --git a/Cargo.toml b/Cargo.toml index 304d3a7..8473067 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,27 +43,27 @@ crate-type = ["cdylib", "rlib"] [dependencies] # Core -serde_core = { version = "1.0.226", default-features = false, features = [ +serde_core = { version = "1.0.228", default-features = false, features = [ "alloc", ] } -indexmap = { version = "2.11.4", features = [ +indexmap = { version = "2.12.1", features = [ "serde", ], default-features = false } -logos = { version = "0.15.1", default-features = false, features = [ +logos = { version = "0.16.0", default-features = false, features = [ "export_derive", ] } lalrpop-util = { version = "0.22.2", features = ["lexer"] } -itoa = "1.0.15" -thiserror = "2.0.16" -hashbrown = "0.16.0" +itoa = "1.0.16" +thiserror = "2.0.17" +hashbrown = "0.16.1" # WASM support (optional) -wasm-bindgen = { version = "0.2.104", optional = true } +wasm-bindgen = { version = "0.2.106", optional = true } serde-wasm-bindgen = { version = "0.6.5", optional = true } console_error_panic_hook = { version = "0.1.7", optional = true } # Lua support (optional) -mlua = { version = "0.11.3", features = [ +mlua = { version = "0.11.5", features = [ "module", "macros", "serialize", @@ -73,17 +73,17 @@ mlua = { version = "0.11.3", features = [ lalrpop = "0.22.2" [dev-dependencies] -wasm-bindgen-test = { version = "0.3.54" } -serde_json = "1.0.145" +wasm-bindgen-test = { version = "0.3.56" } +serde_json = "1.0.147" serde_norway = "0.9.42" serde_bytes = "0.11.19" -toml_edit = { version = "0.23.6", features = ["serde"] } +toml_edit = { version = "0.23.9", features = ["serde"] } anyhow = "1.0.100" paste = "1.0.15" -serde = { version = "1.0.226", features = ["derive"] } +serde = { version = "1.0.228", features = ["derive"] } [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] -criterion = { version = "0.7.0", features = ["html_reports"] } +criterion = { version = "0.8.1", features = ["html_reports"] } [profile.release] lto = true diff --git a/benches/serde.rs b/benches/serde.rs index 6f2b301..ad2227a 100644 --- a/benches/serde.rs +++ b/benches/serde.rs @@ -1,4 +1,4 @@ -use criterion::{criterion_group, criterion_main, Criterion, Throughput}; +use criterion::{Criterion, Throughput, criterion_group, criterion_main}; use serde::Deserialize; use std::hint::black_box; From 1fa5c0954402a1af8b1344168c23b5d52df993c2 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Wed, 24 Dec 2025 11:33:01 +0100 Subject: [PATCH 67/68] Nuke benches and custom tests in favor of the test-suite --- Cargo.lock | 319 ++------- Cargo.toml | 32 +- assets/inputs/array.corn | 3 - assets/inputs/basic.corn | 3 - assets/inputs/basic_empty_let.corn | 3 - assets/inputs/boolean.corn | 4 - assets/inputs/chained.corn | 3 - assets/inputs/chained_complex.corn | 8 - assets/inputs/char.corn | 3 - assets/inputs/comment.corn | 4 - assets/inputs/compact.corn | 15 - assets/inputs/complex.corn | 56 -- assets/inputs/complex_keys.corn | 9 - assets/inputs/environment_variable.corn | 3 - assets/inputs/float.corn | 4 - assets/inputs/input.corn | 18 - assets/inputs/input_references_input.corn | 6 - assets/inputs/integer.corn | 38 - assets/inputs/invalid.corn | 1 - assets/inputs/invalid_input.corn | 3 - assets/inputs/invalid_nesting.corn | 4 - assets/inputs/invalid_spread.corn | 6 - assets/inputs/mixed_array.corn | 3 - assets/inputs/null.corn | 3 - assets/inputs/null_in_array.corn | 3 - assets/inputs/object.corn | 5 - assets/inputs/object_in_array.corn | 3 - assets/inputs/quoted_keys.corn | 8 - assets/inputs/readme_example.corn | 28 - assets/inputs/spread.corn | 10 - assets/inputs/string.corn | 6 - assets/inputs/string_interpolation.corn | 7 - assets/inputs/string_multiline.corn | 6 - assets/inputs/unicode.corn | 6 - assets/inputs/value_after_table.corn | 4 - assets/inputs/very_compact.corn | 1 - assets/outputs/json/array.json | 7 - assets/outputs/json/basic.json | 3 - assets/outputs/json/basic_empty_let.json | 3 - assets/outputs/json/boolean.json | 4 - assets/outputs/json/chained.json | 5 - assets/outputs/json/chained_complex.json | 12 - assets/outputs/json/char.json | 3 - assets/outputs/json/comment.json | 3 - assets/outputs/json/compact.json | 50 -- assets/outputs/json/complex.json | 45 -- assets/outputs/json/complex_keys.json | 13 - assets/outputs/json/environment_variable.json | 3 - assets/outputs/json/float.json | 4 - assets/outputs/json/input.json | 11 - .../outputs/json/input_references_input.json | 3 - assets/outputs/json/integer.json | 29 - assets/outputs/json/invalid.json | 0 assets/outputs/json/invalid_input.json | 0 assets/outputs/json/invalid_nesting.json | 0 assets/outputs/json/invalid_spread.json | 0 assets/outputs/json/mixed_array.json | 7 - assets/outputs/json/null.json | 3 - assets/outputs/json/null_in_array.json | 5 - assets/outputs/json/object.json | 5 - assets/outputs/json/object_in_array.json | 8 - assets/outputs/json/quoted_keys.json | 12 - assets/outputs/json/readme_example.json | 34 - assets/outputs/json/spread.json | 10 - assets/outputs/json/string.json | 6 - assets/outputs/json/string_interpolation.json | 4 - assets/outputs/json/string_multiline.json | 3 - assets/outputs/json/unicode.json | 6 - assets/outputs/json/value_after_table.json | 4 - assets/outputs/json/very_compact.json | 50 -- assets/outputs/toml/array.toml | 6 - assets/outputs/toml/basic.toml | 2 - assets/outputs/toml/basic_empty_let.toml | 2 - assets/outputs/toml/boolean.toml | 3 - assets/outputs/toml/chained.toml | 3 - assets/outputs/toml/chained_complex.toml | 10 - assets/outputs/toml/char.toml | 2 - assets/outputs/toml/comment.toml | 2 - assets/outputs/toml/compact.toml | 47 -- assets/outputs/toml/complex.toml | 34 - assets/outputs/toml/complex_keys.toml | 12 - assets/outputs/toml/environment_variable.toml | 2 - assets/outputs/toml/float.toml | 3 - assets/outputs/toml/input.toml | 9 - .../outputs/toml/input_references_input.toml | 2 - assets/outputs/toml/integer.toml | 28 - assets/outputs/toml/invalid.toml | 0 assets/outputs/toml/invalid_input.toml | 0 assets/outputs/toml/invalid_nesting.toml | 0 assets/outputs/toml/invalid_spread.toml | 0 assets/outputs/toml/mixed_array.toml | 6 - assets/outputs/toml/null.toml | 1 - assets/outputs/toml/null_in_array.toml | 0 assets/outputs/toml/object.toml | 3 - assets/outputs/toml/object_in_array.toml | 4 - assets/outputs/toml/quoted_keys.toml | 9 - assets/outputs/toml/readme_example.toml | 30 - assets/outputs/toml/spread.toml | 9 - assets/outputs/toml/string.toml | 7 - assets/outputs/toml/string_interpolation.toml | 3 - assets/outputs/toml/string_multiline.toml | 5 - assets/outputs/toml/unicode.toml | 5 - assets/outputs/toml/value_after_table.toml | 4 - assets/outputs/toml/very_compact.toml | 47 -- assets/outputs/yaml/array.yml | 5 - assets/outputs/yaml/basic.yml | 2 - assets/outputs/yaml/basic_empty_let.yml | 2 - assets/outputs/yaml/boolean.yml | 3 - assets/outputs/yaml/chained.yml | 3 - assets/outputs/yaml/chained_complex.yml | 8 - assets/outputs/yaml/char.yml | 2 - assets/outputs/yaml/comment.yml | 2 - assets/outputs/yaml/compact.yml | 37 - assets/outputs/yaml/complex.yml | 34 - assets/outputs/yaml/complex_keys.yml | 10 - assets/outputs/yaml/environment_variable.yml | 2 - assets/outputs/yaml/float.yml | 3 - assets/outputs/yaml/input.yml | 8 - .../outputs/yaml/input_references_input.yml | 2 - assets/outputs/yaml/integer.yml | 28 - assets/outputs/yaml/invalid.yml | 0 assets/outputs/yaml/invalid_input.yml | 0 assets/outputs/yaml/invalid_nesting.yml | 0 assets/outputs/yaml/invalid_spread.yml | 0 assets/outputs/yaml/mixed_array.yml | 5 - assets/outputs/yaml/null.yml | 2 - assets/outputs/yaml/null_in_array.yml | 3 - assets/outputs/yaml/object.yml | 3 - assets/outputs/yaml/object_in_array.yml | 4 - assets/outputs/yaml/quoted_keys.yml | 9 - assets/outputs/yaml/readme_example.yml | 24 - assets/outputs/yaml/spread.yml | 8 - assets/outputs/yaml/string.yml | 5 - assets/outputs/yaml/string_interpolation.yml | 3 - assets/outputs/yaml/string_multiline.yml | 4 - assets/outputs/yaml/unicode.yml | 5 - assets/outputs/yaml/value_after_table.yml | 3 - assets/outputs/yaml/very_compact.yml | 37 - benches/serde.rs | 453 ------------ tests/borrowed_tests.rs | 191 ----- tests/de_tests.rs | 652 ------------------ tests/parser_tests.rs | 106 --- tests/test_suite.rs | 32 + 143 files changed, 94 insertions(+), 2899 deletions(-) delete mode 100644 assets/inputs/array.corn delete mode 100644 assets/inputs/basic.corn delete mode 100644 assets/inputs/basic_empty_let.corn delete mode 100644 assets/inputs/boolean.corn delete mode 100644 assets/inputs/chained.corn delete mode 100644 assets/inputs/chained_complex.corn delete mode 100644 assets/inputs/char.corn delete mode 100644 assets/inputs/comment.corn delete mode 100644 assets/inputs/compact.corn delete mode 100644 assets/inputs/complex.corn delete mode 100644 assets/inputs/complex_keys.corn delete mode 100644 assets/inputs/environment_variable.corn delete mode 100644 assets/inputs/float.corn delete mode 100644 assets/inputs/input.corn delete mode 100644 assets/inputs/input_references_input.corn delete mode 100644 assets/inputs/integer.corn delete mode 100644 assets/inputs/invalid.corn delete mode 100644 assets/inputs/invalid_input.corn delete mode 100644 assets/inputs/invalid_nesting.corn delete mode 100644 assets/inputs/invalid_spread.corn delete mode 100644 assets/inputs/mixed_array.corn delete mode 100644 assets/inputs/null.corn delete mode 100644 assets/inputs/null_in_array.corn delete mode 100644 assets/inputs/object.corn delete mode 100644 assets/inputs/object_in_array.corn delete mode 100644 assets/inputs/quoted_keys.corn delete mode 100644 assets/inputs/readme_example.corn delete mode 100644 assets/inputs/spread.corn delete mode 100644 assets/inputs/string.corn delete mode 100644 assets/inputs/string_interpolation.corn delete mode 100644 assets/inputs/string_multiline.corn delete mode 100644 assets/inputs/unicode.corn delete mode 100644 assets/inputs/value_after_table.corn delete mode 100644 assets/inputs/very_compact.corn delete mode 100644 assets/outputs/json/array.json delete mode 100644 assets/outputs/json/basic.json delete mode 100644 assets/outputs/json/basic_empty_let.json delete mode 100644 assets/outputs/json/boolean.json delete mode 100644 assets/outputs/json/chained.json delete mode 100644 assets/outputs/json/chained_complex.json delete mode 100644 assets/outputs/json/char.json delete mode 100644 assets/outputs/json/comment.json delete mode 100644 assets/outputs/json/compact.json delete mode 100644 assets/outputs/json/complex.json delete mode 100644 assets/outputs/json/complex_keys.json delete mode 100644 assets/outputs/json/environment_variable.json delete mode 100644 assets/outputs/json/float.json delete mode 100644 assets/outputs/json/input.json delete mode 100644 assets/outputs/json/input_references_input.json delete mode 100644 assets/outputs/json/integer.json delete mode 100644 assets/outputs/json/invalid.json delete mode 100644 assets/outputs/json/invalid_input.json delete mode 100644 assets/outputs/json/invalid_nesting.json delete mode 100644 assets/outputs/json/invalid_spread.json delete mode 100644 assets/outputs/json/mixed_array.json delete mode 100644 assets/outputs/json/null.json delete mode 100644 assets/outputs/json/null_in_array.json delete mode 100644 assets/outputs/json/object.json delete mode 100644 assets/outputs/json/object_in_array.json delete mode 100644 assets/outputs/json/quoted_keys.json delete mode 100644 assets/outputs/json/readme_example.json delete mode 100644 assets/outputs/json/spread.json delete mode 100644 assets/outputs/json/string.json delete mode 100644 assets/outputs/json/string_interpolation.json delete mode 100644 assets/outputs/json/string_multiline.json delete mode 100644 assets/outputs/json/unicode.json delete mode 100644 assets/outputs/json/value_after_table.json delete mode 100644 assets/outputs/json/very_compact.json delete mode 100644 assets/outputs/toml/array.toml delete mode 100644 assets/outputs/toml/basic.toml delete mode 100644 assets/outputs/toml/basic_empty_let.toml delete mode 100644 assets/outputs/toml/boolean.toml delete mode 100644 assets/outputs/toml/chained.toml delete mode 100644 assets/outputs/toml/chained_complex.toml delete mode 100644 assets/outputs/toml/char.toml delete mode 100644 assets/outputs/toml/comment.toml delete mode 100644 assets/outputs/toml/compact.toml delete mode 100644 assets/outputs/toml/complex.toml delete mode 100644 assets/outputs/toml/complex_keys.toml delete mode 100644 assets/outputs/toml/environment_variable.toml delete mode 100644 assets/outputs/toml/float.toml delete mode 100644 assets/outputs/toml/input.toml delete mode 100644 assets/outputs/toml/input_references_input.toml delete mode 100644 assets/outputs/toml/integer.toml delete mode 100644 assets/outputs/toml/invalid.toml delete mode 100644 assets/outputs/toml/invalid_input.toml delete mode 100644 assets/outputs/toml/invalid_nesting.toml delete mode 100644 assets/outputs/toml/invalid_spread.toml delete mode 100644 assets/outputs/toml/mixed_array.toml delete mode 100644 assets/outputs/toml/null.toml delete mode 100644 assets/outputs/toml/null_in_array.toml delete mode 100644 assets/outputs/toml/object.toml delete mode 100644 assets/outputs/toml/object_in_array.toml delete mode 100644 assets/outputs/toml/quoted_keys.toml delete mode 100644 assets/outputs/toml/readme_example.toml delete mode 100644 assets/outputs/toml/spread.toml delete mode 100644 assets/outputs/toml/string.toml delete mode 100644 assets/outputs/toml/string_interpolation.toml delete mode 100644 assets/outputs/toml/string_multiline.toml delete mode 100644 assets/outputs/toml/unicode.toml delete mode 100644 assets/outputs/toml/value_after_table.toml delete mode 100644 assets/outputs/toml/very_compact.toml delete mode 100644 assets/outputs/yaml/array.yml delete mode 100644 assets/outputs/yaml/basic.yml delete mode 100644 assets/outputs/yaml/basic_empty_let.yml delete mode 100644 assets/outputs/yaml/boolean.yml delete mode 100644 assets/outputs/yaml/chained.yml delete mode 100644 assets/outputs/yaml/chained_complex.yml delete mode 100644 assets/outputs/yaml/char.yml delete mode 100644 assets/outputs/yaml/comment.yml delete mode 100644 assets/outputs/yaml/compact.yml delete mode 100644 assets/outputs/yaml/complex.yml delete mode 100644 assets/outputs/yaml/complex_keys.yml delete mode 100644 assets/outputs/yaml/environment_variable.yml delete mode 100644 assets/outputs/yaml/float.yml delete mode 100644 assets/outputs/yaml/input.yml delete mode 100644 assets/outputs/yaml/input_references_input.yml delete mode 100644 assets/outputs/yaml/integer.yml delete mode 100644 assets/outputs/yaml/invalid.yml delete mode 100644 assets/outputs/yaml/invalid_input.yml delete mode 100644 assets/outputs/yaml/invalid_nesting.yml delete mode 100644 assets/outputs/yaml/invalid_spread.yml delete mode 100644 assets/outputs/yaml/mixed_array.yml delete mode 100644 assets/outputs/yaml/null.yml delete mode 100644 assets/outputs/yaml/null_in_array.yml delete mode 100644 assets/outputs/yaml/object.yml delete mode 100644 assets/outputs/yaml/object_in_array.yml delete mode 100644 assets/outputs/yaml/quoted_keys.yml delete mode 100644 assets/outputs/yaml/readme_example.yml delete mode 100644 assets/outputs/yaml/spread.yml delete mode 100644 assets/outputs/yaml/string.yml delete mode 100644 assets/outputs/yaml/string_interpolation.yml delete mode 100644 assets/outputs/yaml/string_multiline.yml delete mode 100644 assets/outputs/yaml/unicode.yml delete mode 100644 assets/outputs/yaml/value_after_table.yml delete mode 100644 assets/outputs/yaml/very_compact.yml delete mode 100644 benches/serde.rs delete mode 100644 tests/borrowed_tests.rs delete mode 100644 tests/de_tests.rs delete mode 100644 tests/parser_tests.rs create mode 100644 tests/test_suite.rs diff --git a/Cargo.lock b/Cargo.lock index 553a8d5..033baca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,27 +11,12 @@ dependencies = [ "memchr", ] -[[package]] -name = "alloca" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4" -dependencies = [ - "cc", -] - [[package]] name = "allocator-api2" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - [[package]] name = "anstream" version = "0.6.21" @@ -82,12 +67,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "anyhow" -version = "1.0.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" - [[package]] name = "ascii-canvas" version = "4.0.0" @@ -166,6 +145,12 @@ version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +[[package]] +name = "camino" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" + [[package]] name = "cast" version = "0.3.0" @@ -188,33 +173,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - [[package]] name = "clap" version = "4.5.53" @@ -302,72 +260,6 @@ dependencies = [ "libc", ] -[[package]] -name = "criterion" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d883447757bb0ee46f233e9dc22eb84d93a9508c9b868687b274fc431d886bf" -dependencies = [ - "alloca", - "anes", - "cast", - "ciborium", - "clap", - "criterion-plot", - "itertools 0.13.0", - "num-traits", - "oorandom", - "page_size", - "plotters", - "rayon", - "regex", - "serde", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed943f81ea2faa8dcecbbfa50164acf95d555afec96a27871663b300e387b2e4" -dependencies = [ - "cast", - "itertools 0.13.0", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - [[package]] name = "crypto-common" version = "0.1.7" @@ -378,6 +270,18 @@ dependencies = [ "typenum", ] +[[package]] +name = "datatest-stable" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a867d7322eb69cf3a68a5426387a25b45cb3b9c5ee41023ee6cea92e2afadd82" +dependencies = [ + "camino", + "fancy-regex", + "libtest-mimic", + "walkdir", +] + [[package]] name = "digest" version = "0.10.7" @@ -420,6 +324,23 @@ dependencies = [ "typeid", ] +[[package]] +name = "escape8259" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5692dd7b5a1978a5aeb0ce83b7655c58ca8efdcb79d21036ea249da95afec2c6" + +[[package]] +name = "fancy-regex" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298" +dependencies = [ + "bit-set", + "regex-automata", + "regex-syntax", +] + [[package]] name = "find-msvc-tools" version = "0.1.5" @@ -454,17 +375,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "half" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" -dependencies = [ - "cfg-if", - "crunchy", - "zerocopy", -] - [[package]] name = "hashbrown" version = "0.16.1" @@ -500,15 +410,6 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.14.0" @@ -552,7 +453,7 @@ dependencies = [ "ascii-canvas", "bit-set", "ena", - "itertools 0.14.0", + "itertools", "lalrpop-util", "petgraph", "pico-args", @@ -585,9 +486,8 @@ checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" name = "libcorn" version = "0.10.0" dependencies = [ - "anyhow", "console_error_panic_hook", - "criterion", + "datatest-stable", "hashbrown", "indexmap", "itoa", @@ -595,15 +495,10 @@ dependencies = [ "lalrpop-util", "logos", "mlua", - "paste", - "serde", "serde-wasm-bindgen", - "serde_bytes", "serde_core", "serde_json", - "serde_norway", "thiserror", - "toml_edit", "wasm-bindgen", "wasm-bindgen-test", ] @@ -614,6 +509,18 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "libtest-mimic" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5297962ef19edda4ce33aaa484386e0a5b3d7f2f4e037cbeee00503ef6b29d33" +dependencies = [ + "anstream", + "anstyle", + "clap", + "escape8259", +] + [[package]] name = "lock_api" version = "0.4.14" @@ -716,7 +623,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "465bddde514c4eb3b50b543250e97c1d4b284fa3ef7dc0ba2992c77545dbceb2" dependencies = [ - "itertools 0.14.0", + "itertools", "once_cell", "proc-macro-error2", "proc-macro2", @@ -777,16 +684,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "page_size" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "parking_lot" version = "0.12.5" @@ -810,12 +707,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - [[package]] name = "petgraph" version = "0.7.1" @@ -847,34 +738,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" -[[package]] -name = "plotters" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" - -[[package]] -name = "plotters-svg" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" -dependencies = [ - "plotters-backend", -] - [[package]] name = "precomputed-hash" version = "0.1.1" @@ -921,26 +784,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rayon" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - [[package]] name = "redox_syscall" version = "0.5.18" @@ -1058,16 +901,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "serde_bytes" -version = "0.11.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" -dependencies = [ - "serde", - "serde_core", -] - [[package]] name = "serde_core" version = "1.0.228" @@ -1209,16 +1042,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "toml_datetime" version = "0.7.5+spec-1.1.0" @@ -1410,22 +1233,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" version = "0.1.11" @@ -1435,12 +1242,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-link" version = "0.2.1" @@ -1538,26 +1339,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "zerocopy" -version = "0.8.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "zmij" version = "0.1.7" diff --git a/Cargo.toml b/Cargo.toml index 8473067..fe8c273 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,6 +41,15 @@ luajit52 = ["dep:mlua", "mlua/luajit52"] name = "corn" crate-type = ["cdylib", "rlib"] +[[test]] +name = "test_suite" +harness = false + +[profile.release] +lto = true +codegen-units = 1 +strip = true + [dependencies] # Core serde_core = { version = "1.0.228", default-features = false, features = [ @@ -69,30 +78,13 @@ mlua = { version = "0.11.5", features = [ "serialize", ], optional = true } -[build-dependencies] -lalrpop = "0.22.2" - [dev-dependencies] wasm-bindgen-test = { version = "0.3.56" } serde_json = "1.0.147" -serde_norway = "0.9.42" -serde_bytes = "0.11.19" -toml_edit = { version = "0.23.9", features = ["serde"] } -anyhow = "1.0.100" -paste = "1.0.15" -serde = { version = "1.0.228", features = ["derive"] } +datatest-stable = "0.3.3" -[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] -criterion = { version = "0.8.1", features = ["html_reports"] } - -[profile.release] -lto = true -codegen-units = 1 -strip = true - -[[bench]] -name = "serde" -harness = false +[build-dependencies] +lalrpop = "0.22.2" [package.metadata.wasm-pack.profile.profiling] wasm-opt = ['-O', '--enable-bulk-memory'] diff --git a/assets/inputs/array.corn b/assets/inputs/array.corn deleted file mode 100644 index ea95311..0000000 --- a/assets/inputs/array.corn +++ /dev/null @@ -1,3 +0,0 @@ -{ - foo = [ 1 2 3 ] -} diff --git a/assets/inputs/basic.corn b/assets/inputs/basic.corn deleted file mode 100644 index 7524a1b..0000000 --- a/assets/inputs/basic.corn +++ /dev/null @@ -1,3 +0,0 @@ -{ - foo = "bar" -} diff --git a/assets/inputs/basic_empty_let.corn b/assets/inputs/basic_empty_let.corn deleted file mode 100644 index ea902d2..0000000 --- a/assets/inputs/basic_empty_let.corn +++ /dev/null @@ -1,3 +0,0 @@ -let { } in { - foo = "bar" -} diff --git a/assets/inputs/boolean.corn b/assets/inputs/boolean.corn deleted file mode 100644 index c1b7434..0000000 --- a/assets/inputs/boolean.corn +++ /dev/null @@ -1,4 +0,0 @@ -{ - foo = true - bar = false -} diff --git a/assets/inputs/chained.corn b/assets/inputs/chained.corn deleted file mode 100644 index d88ee32..0000000 --- a/assets/inputs/chained.corn +++ /dev/null @@ -1,3 +0,0 @@ -{ - foo.bar = "baz" -} diff --git a/assets/inputs/chained_complex.corn b/assets/inputs/chained_complex.corn deleted file mode 100644 index 6fce998..0000000 --- a/assets/inputs/chained_complex.corn +++ /dev/null @@ -1,8 +0,0 @@ -{ - foo = { - bar.baz = 42 - qux = true - } - - foo.quux = [ "green eggs" "ham" ] -} diff --git a/assets/inputs/char.corn b/assets/inputs/char.corn deleted file mode 100644 index d32b4a6..0000000 --- a/assets/inputs/char.corn +++ /dev/null @@ -1,3 +0,0 @@ -{ - foo = "a" -} diff --git a/assets/inputs/comment.corn b/assets/inputs/comment.corn deleted file mode 100644 index d1bd72f..0000000 --- a/assets/inputs/comment.corn +++ /dev/null @@ -1,4 +0,0 @@ -{ - // single line comment - foo = "bar" // mixed line comment -} diff --git a/assets/inputs/compact.corn b/assets/inputs/compact.corn deleted file mode 100644 index 0e78286..0000000 --- a/assets/inputs/compact.corn +++ /dev/null @@ -1,15 +0,0 @@ -{ - one={foo="bar" bar="foo"} - two={foo=1 bar=2} - three={foo=1.0 bar=2.0} - four={foo=true bar=false} - five={foo=null bar=null} - six={foo={} bar={}} - seven={foo=[] bar=[]} - - eight=["foo""bar"] - nine=[true false] - ten=[1 2] - eleven=[[][]] - twelve=[{}{}] -} diff --git a/assets/inputs/complex.corn b/assets/inputs/complex.corn deleted file mode 100644 index 5710752..0000000 --- a/assets/inputs/complex.corn +++ /dev/null @@ -1,56 +0,0 @@ -let { - // inputs go here - // they should start with a $ and use alphanumeric characters only - $firstName = "John" - $lastName = "Smith" - $age = 32 - $employed = true - $jobName = "Postman" -} -in { - // here is another comment - name.first = $firstName - name.last = $lastName - name.full = "${firstName} ${lastName}" - age = $age - - employment = { - employed = $employed - name = $jobName - } - - placeholder = null - - // invalid = not_valid - // invalid.var = $not_valid - - employment.sinceYear = 2019 - - parents.father.birthday = { - year = 1970 - month = 2 - day = 3 - } - - gender = "M" - - favourites = [ - "blue" - "fish" - "egg" - $jobName - 4.73753 - false - { - hello = "world" - food.favourite = "egg" - food.hated = "beef" - } - ] - - empty1 = {} - empty2 = [] - - negative.int = -34 - negative.float = -34.34 -} diff --git a/assets/inputs/complex_keys.corn b/assets/inputs/complex_keys.corn deleted file mode 100644 index fca06cc..0000000 --- a/assets/inputs/complex_keys.corn +++ /dev/null @@ -1,9 +0,0 @@ -{ - with_underscore = 0 - with-dash = 1 - with_🌽 = 2 - !£$%^&*()_ = 3 - j12345 = 4 - foo.bar-baz = "hello" - apple-pie.crust = "yum" -} diff --git a/assets/inputs/environment_variable.corn b/assets/inputs/environment_variable.corn deleted file mode 100644 index 492ed48..0000000 --- a/assets/inputs/environment_variable.corn +++ /dev/null @@ -1,3 +0,0 @@ -{ - foo = $env_CORN_TEST -} diff --git a/assets/inputs/float.corn b/assets/inputs/float.corn deleted file mode 100644 index 281a020..0000000 --- a/assets/inputs/float.corn +++ /dev/null @@ -1,4 +0,0 @@ -{ - foo = 3.14159 - bar = 1.01e+2 -} diff --git a/assets/inputs/input.corn b/assets/inputs/input.corn deleted file mode 100644 index b017482..0000000 --- a/assets/inputs/input.corn +++ /dev/null @@ -1,18 +0,0 @@ -let { - $firstName = "John" - $lastName = "Smith" - - $birthday = { - day = 1 - month = 1 - year = 1970 - } - -} in { - name = { - first = $firstName - last = $lastName - } - - dob = $birthday -} diff --git a/assets/inputs/input_references_input.corn b/assets/inputs/input_references_input.corn deleted file mode 100644 index f55d88b..0000000 --- a/assets/inputs/input_references_input.corn +++ /dev/null @@ -1,6 +0,0 @@ -let { - $foo = "bar" - $baz = $foo -} in { - foo = $baz -} diff --git a/assets/inputs/integer.corn b/assets/inputs/integer.corn deleted file mode 100644 index 8673268..0000000 --- a/assets/inputs/integer.corn +++ /dev/null @@ -1,38 +0,0 @@ -{ - // Basic decimal integers - positive_decimal = 42 - negative_decimal = -123 - zero = 0 - - // Decimal with underscores - large_decimal = 1_000_000 - negative_large_decimal = -1_234_567 - decimal_with_underscores = 12_34_56 - - // Hexadecimal integers - hex_lowercase = 0xfafafa - hex_uppercase = 0xFF - hex_mixed = 0xAbCdEf - negative_hex = -0xABC - hex_with_underscores = 0xFA_FA_FA - negative_hex_underscores = -0xAB_CD_EF - hex_single_digit = 0xF - hex_zero = 0x0 - - // Octal integers - octal_basic = 0o755 - octal_zero = 0o0 - negative_octal = -0o123 - octal_with_underscores = 0o12_34_56 - negative_octal_underscores = -0o76_54_32 - octal_single_digit = 0o7 - - // Binary integers - binary_basic = 0b1010 - binary_zero = 0b0 - negative_binary = -0b1100 - binary_with_underscores = 0b1010_1100_1111 - negative_binary_underscores = -0b1100_0011 - binary_single_digit = 0b1 - binary_all_ones = 0b1111 -} diff --git a/assets/inputs/invalid.corn b/assets/inputs/invalid.corn deleted file mode 100644 index cc354da..0000000 --- a/assets/inputs/invalid.corn +++ /dev/null @@ -1 +0,0 @@ -this is not valid corn config diff --git a/assets/inputs/invalid_input.corn b/assets/inputs/invalid_input.corn deleted file mode 100644 index 6160d94..0000000 --- a/assets/inputs/invalid_input.corn +++ /dev/null @@ -1,3 +0,0 @@ -{ - foo = $bar -} diff --git a/assets/inputs/invalid_nesting.corn b/assets/inputs/invalid_nesting.corn deleted file mode 100644 index 8726fef..0000000 --- a/assets/inputs/invalid_nesting.corn +++ /dev/null @@ -1,4 +0,0 @@ -{ - foo = 0 - foo.bar = 1 -} diff --git a/assets/inputs/invalid_spread.corn b/assets/inputs/invalid_spread.corn deleted file mode 100644 index 39b1ab1..0000000 --- a/assets/inputs/invalid_spread.corn +++ /dev/null @@ -1,6 +0,0 @@ -let { - $foo = 23 -} in { - ..$foo - bar = [ ..$foo ] -} diff --git a/assets/inputs/mixed_array.corn b/assets/inputs/mixed_array.corn deleted file mode 100644 index 67276de..0000000 --- a/assets/inputs/mixed_array.corn +++ /dev/null @@ -1,3 +0,0 @@ -{ - foo = [ 1 "two" false ] -} diff --git a/assets/inputs/null.corn b/assets/inputs/null.corn deleted file mode 100644 index 35256da..0000000 --- a/assets/inputs/null.corn +++ /dev/null @@ -1,3 +0,0 @@ -{ - foo = null -} diff --git a/assets/inputs/null_in_array.corn b/assets/inputs/null_in_array.corn deleted file mode 100644 index a2518b7..0000000 --- a/assets/inputs/null_in_array.corn +++ /dev/null @@ -1,3 +0,0 @@ -{ - foo = [ null ] -} \ No newline at end of file diff --git a/assets/inputs/object.corn b/assets/inputs/object.corn deleted file mode 100644 index b932350..0000000 --- a/assets/inputs/object.corn +++ /dev/null @@ -1,5 +0,0 @@ -{ - foo = { - bar = 42 - } -} diff --git a/assets/inputs/object_in_array.corn b/assets/inputs/object_in_array.corn deleted file mode 100644 index dfb5e61..0000000 --- a/assets/inputs/object_in_array.corn +++ /dev/null @@ -1,3 +0,0 @@ -{ - foo = [ { foo = 1 bar = 2 } ] -} diff --git a/assets/inputs/quoted_keys.corn b/assets/inputs/quoted_keys.corn deleted file mode 100644 index dd3e0f6..0000000 --- a/assets/inputs/quoted_keys.corn +++ /dev/null @@ -1,8 +0,0 @@ -{ - 'foo.bar' = 42 - 'green.eggs'.and.ham = "hello world" - 'with spaces' = true - 'escaped\'quote' = false - 'escaped=equals' = -3 - 'normal"quotes' = "funny" -} \ No newline at end of file diff --git a/assets/inputs/readme_example.corn b/assets/inputs/readme_example.corn deleted file mode 100644 index 2ace342..0000000 --- a/assets/inputs/readme_example.corn +++ /dev/null @@ -1,28 +0,0 @@ -let { - $entry = "dist/index.js" - $author = { name = "John Smith" email = "mail@example.com" } -} in { - name = "example-package" - version = "1.0.0" - main = $entry - bin.filebrowser = $entry - private = false - - author = $author - author.url = "https://example.com" - - contributors = [ $author ] - - scripts.build = "tsc" - scripts.run = "node dist" - - dependencies = { - dotenv = "^8.2.0" - // put the rest of your deps here... - } - - devDependencies.typescript = "^4.5" - - config.port = 8080 - config.hostname = null -} diff --git a/assets/inputs/spread.corn b/assets/inputs/spread.corn deleted file mode 100644 index 966128c..0000000 --- a/assets/inputs/spread.corn +++ /dev/null @@ -1,10 +0,0 @@ -let { - $foo = { bar = "baz" } - - $nums_low = [ 1 2 ] - $num_high = [ 3 4 ] -} in { - hello = "world" - ..$foo - nums = [ ..$nums_low ..$num_high ] -} diff --git a/assets/inputs/string.corn b/assets/inputs/string.corn deleted file mode 100644 index 52a29c4..0000000 --- a/assets/inputs/string.corn +++ /dev/null @@ -1,6 +0,0 @@ -{ - foo = "bar" - bar = "\"\\\n\r\t" - baz = "\u{0061}" - qux = "" -} diff --git a/assets/inputs/string_interpolation.corn b/assets/inputs/string_interpolation.corn deleted file mode 100644 index 4b0dd10..0000000 --- a/assets/inputs/string_interpolation.corn +++ /dev/null @@ -1,7 +0,0 @@ -let { - $greeting = "hello" - $subject = "world" -} in { - foo = "${greeting}, ${subject}" - bar = "\$escaped" -} diff --git a/assets/inputs/string_multiline.corn b/assets/inputs/string_multiline.corn deleted file mode 100644 index c1d25a0..0000000 --- a/assets/inputs/string_multiline.corn +++ /dev/null @@ -1,6 +0,0 @@ -{ - foo = " - hello - world - " -} \ No newline at end of file diff --git a/assets/inputs/unicode.corn b/assets/inputs/unicode.corn deleted file mode 100644 index 2b027c4..0000000 --- a/assets/inputs/unicode.corn +++ /dev/null @@ -1,6 +0,0 @@ -{ - plane0 = "\u{053E}" - plane1 = "\u{10514}" - plane2 = "\u{2B77C}" - plane3 = "\u{3106C}" -} \ No newline at end of file diff --git a/assets/inputs/value_after_table.corn b/assets/inputs/value_after_table.corn deleted file mode 100644 index d9575ce..0000000 --- a/assets/inputs/value_after_table.corn +++ /dev/null @@ -1,4 +0,0 @@ -{ - foo = {} - qux = true -} diff --git a/assets/inputs/very_compact.corn b/assets/inputs/very_compact.corn deleted file mode 100644 index 4af65a8..0000000 --- a/assets/inputs/very_compact.corn +++ /dev/null @@ -1 +0,0 @@ -{one={foo="bar" bar="foo"} two={foo=1 bar=2} three={foo=1.0 bar=2.0} four={foo=true bar=false} five={foo=null bar=null} six={foo={} bar={}} seven={foo=[] bar=[]} eight=["foo""bar"] nine=[true false] ten=[1 2] eleven=[[][]] twelve=[{}{}]} diff --git a/assets/outputs/json/array.json b/assets/outputs/json/array.json deleted file mode 100644 index 4dcd9c9..0000000 --- a/assets/outputs/json/array.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "foo": [ - 1, - 2, - 3 - ] -} diff --git a/assets/outputs/json/basic.json b/assets/outputs/json/basic.json deleted file mode 100644 index c8c4105..0000000 --- a/assets/outputs/json/basic.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "foo": "bar" -} diff --git a/assets/outputs/json/basic_empty_let.json b/assets/outputs/json/basic_empty_let.json deleted file mode 100644 index c8c4105..0000000 --- a/assets/outputs/json/basic_empty_let.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "foo": "bar" -} diff --git a/assets/outputs/json/boolean.json b/assets/outputs/json/boolean.json deleted file mode 100644 index 5084f85..0000000 --- a/assets/outputs/json/boolean.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "foo": true, - "bar": false -} diff --git a/assets/outputs/json/chained.json b/assets/outputs/json/chained.json deleted file mode 100644 index faa9156..0000000 --- a/assets/outputs/json/chained.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "foo": { - "bar": "baz" - } -} diff --git a/assets/outputs/json/chained_complex.json b/assets/outputs/json/chained_complex.json deleted file mode 100644 index c87f092..0000000 --- a/assets/outputs/json/chained_complex.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "foo": { - "bar": { - "baz": 42 - }, - "qux": true, - "quux": [ - "green eggs", - "ham" - ] - } -} diff --git a/assets/outputs/json/char.json b/assets/outputs/json/char.json deleted file mode 100644 index 2cb7a47..0000000 --- a/assets/outputs/json/char.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "foo": "a" -} diff --git a/assets/outputs/json/comment.json b/assets/outputs/json/comment.json deleted file mode 100644 index c8c4105..0000000 --- a/assets/outputs/json/comment.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "foo": "bar" -} diff --git a/assets/outputs/json/compact.json b/assets/outputs/json/compact.json deleted file mode 100644 index 65ecfe0..0000000 --- a/assets/outputs/json/compact.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "one": { - "foo": "bar", - "bar": "foo" - }, - "two": { - "foo": 1, - "bar": 2 - }, - "three": { - "foo": 1.0, - "bar": 2.0 - }, - "four": { - "foo": true, - "bar": false - }, - "five": { - "foo": null, - "bar": null - }, - "six": { - "foo": {}, - "bar": {} - }, - "seven": { - "foo": [], - "bar": [] - }, - "eight": [ - "foo", - "bar" - ], - "nine": [ - true, - false - ], - "ten": [ - 1, - 2 - ], - "eleven": [ - [], - [] - ], - "twelve": [ - {}, - {} - ] -} diff --git a/assets/outputs/json/complex.json b/assets/outputs/json/complex.json deleted file mode 100644 index 89d0f90..0000000 --- a/assets/outputs/json/complex.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": { - "first": "John", - "last": "Smith", - "full": "John Smith" - }, - "age": 32, - "employment": { - "employed": true, - "name": "Postman", - "sinceYear": 2019 - }, - "placeholder": null, - "parents": { - "father": { - "birthday": { - "year": 1970, - "month": 2, - "day": 3 - } - } - }, - "gender": "M", - "favourites": [ - "blue", - "fish", - "egg", - "Postman", - 4.73753, - false, - { - "hello": "world", - "food": { - "favourite": "egg", - "hated": "beef" - } - } - ], - "empty1": {}, - "empty2": [], - "negative": { - "int": -34, - "float": -34.34 - } -} diff --git a/assets/outputs/json/complex_keys.json b/assets/outputs/json/complex_keys.json deleted file mode 100644 index 9b212be..0000000 --- a/assets/outputs/json/complex_keys.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "with_underscore": 0, - "with-dash": 1, - "with_🌽": 2, - "!£$%^&*()_": 3, - "j12345": 4, - "foo": { - "bar-baz": "hello" - }, - "apple-pie": { - "crust": "yum" - } -} diff --git a/assets/outputs/json/environment_variable.json b/assets/outputs/json/environment_variable.json deleted file mode 100644 index c8c4105..0000000 --- a/assets/outputs/json/environment_variable.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "foo": "bar" -} diff --git a/assets/outputs/json/float.json b/assets/outputs/json/float.json deleted file mode 100644 index 1133dc4..0000000 --- a/assets/outputs/json/float.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "foo": 3.14159, - "bar": 101.0 -} diff --git a/assets/outputs/json/input.json b/assets/outputs/json/input.json deleted file mode 100644 index 0920b9d..0000000 --- a/assets/outputs/json/input.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": { - "first": "John", - "last": "Smith" - }, - "dob": { - "day": 1, - "month": 1, - "year": 1970 - } -} diff --git a/assets/outputs/json/input_references_input.json b/assets/outputs/json/input_references_input.json deleted file mode 100644 index c8c4105..0000000 --- a/assets/outputs/json/input_references_input.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "foo": "bar" -} diff --git a/assets/outputs/json/integer.json b/assets/outputs/json/integer.json deleted file mode 100644 index 5855b47..0000000 --- a/assets/outputs/json/integer.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "positive_decimal": 42, - "negative_decimal": -123, - "zero": 0, - "large_decimal": 1000000, - "negative_large_decimal": -1234567, - "decimal_with_underscores": 123456, - "hex_lowercase": 16448250, - "hex_uppercase": 255, - "hex_mixed": 11259375, - "negative_hex": -2748, - "hex_with_underscores": 16448250, - "negative_hex_underscores": -11259375, - "hex_single_digit": 15, - "hex_zero": 0, - "octal_basic": 493, - "octal_zero": 0, - "negative_octal": -83, - "octal_with_underscores": 42798, - "negative_octal_underscores": -256794, - "octal_single_digit": 7, - "binary_basic": 10, - "binary_zero": 0, - "negative_binary": -12, - "binary_with_underscores": 2767, - "negative_binary_underscores": -195, - "binary_single_digit": 1, - "binary_all_ones": 15 -} diff --git a/assets/outputs/json/invalid.json b/assets/outputs/json/invalid.json deleted file mode 100644 index e69de29..0000000 diff --git a/assets/outputs/json/invalid_input.json b/assets/outputs/json/invalid_input.json deleted file mode 100644 index e69de29..0000000 diff --git a/assets/outputs/json/invalid_nesting.json b/assets/outputs/json/invalid_nesting.json deleted file mode 100644 index e69de29..0000000 diff --git a/assets/outputs/json/invalid_spread.json b/assets/outputs/json/invalid_spread.json deleted file mode 100644 index e69de29..0000000 diff --git a/assets/outputs/json/mixed_array.json b/assets/outputs/json/mixed_array.json deleted file mode 100644 index 349c955..0000000 --- a/assets/outputs/json/mixed_array.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "foo": [ - 1, - "two", - false - ] -} diff --git a/assets/outputs/json/null.json b/assets/outputs/json/null.json deleted file mode 100644 index 52f08cd..0000000 --- a/assets/outputs/json/null.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "foo": null -} diff --git a/assets/outputs/json/null_in_array.json b/assets/outputs/json/null_in_array.json deleted file mode 100644 index bfe673a..0000000 --- a/assets/outputs/json/null_in_array.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "foo": [ - null - ] -} diff --git a/assets/outputs/json/object.json b/assets/outputs/json/object.json deleted file mode 100644 index 2ff6c73..0000000 --- a/assets/outputs/json/object.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "foo": { - "bar": 42 - } -} diff --git a/assets/outputs/json/object_in_array.json b/assets/outputs/json/object_in_array.json deleted file mode 100644 index d40b409..0000000 --- a/assets/outputs/json/object_in_array.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "foo": [ - { - "foo": 1, - "bar": 2 - } - ] -} diff --git a/assets/outputs/json/quoted_keys.json b/assets/outputs/json/quoted_keys.json deleted file mode 100644 index a0ed5e5..0000000 --- a/assets/outputs/json/quoted_keys.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "foo.bar": 42, - "green.eggs": { - "and": { - "ham": "hello world" - } - }, - "with spaces": true, - "escaped'quote": false, - "escaped=equals": -3, - "normal\"quotes": "funny" -} diff --git a/assets/outputs/json/readme_example.json b/assets/outputs/json/readme_example.json deleted file mode 100644 index 74233df..0000000 --- a/assets/outputs/json/readme_example.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "example-package", - "version": "1.0.0", - "main": "dist/index.js", - "bin": { - "filebrowser": "dist/index.js" - }, - "private": false, - "author": { - "name": "John Smith", - "email": "mail@example.com", - "url": "https://example.com" - }, - "contributors": [ - { - "name": "John Smith", - "email": "mail@example.com" - } - ], - "scripts": { - "build": "tsc", - "run": "node dist" - }, - "dependencies": { - "dotenv": "^8.2.0" - }, - "devDependencies": { - "typescript": "^4.5" - }, - "config": { - "port": 8080, - "hostname": null - } -} diff --git a/assets/outputs/json/spread.json b/assets/outputs/json/spread.json deleted file mode 100644 index 632051c..0000000 --- a/assets/outputs/json/spread.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "hello": "world", - "bar": "baz", - "nums": [ - 1, - 2, - 3, - 4 - ] -} diff --git a/assets/outputs/json/string.json b/assets/outputs/json/string.json deleted file mode 100644 index 61c3a14..0000000 --- a/assets/outputs/json/string.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "foo": "bar", - "bar": "\"\\\n\r\t", - "baz": "a", - "qux": "" -} diff --git a/assets/outputs/json/string_interpolation.json b/assets/outputs/json/string_interpolation.json deleted file mode 100644 index 9068aec..0000000 --- a/assets/outputs/json/string_interpolation.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "foo": "hello, world", - "bar": "$escaped" -} diff --git a/assets/outputs/json/string_multiline.json b/assets/outputs/json/string_multiline.json deleted file mode 100644 index 888d65d..0000000 --- a/assets/outputs/json/string_multiline.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "foo": "hello\nworld\n" -} diff --git a/assets/outputs/json/unicode.json b/assets/outputs/json/unicode.json deleted file mode 100644 index f725d8c..0000000 --- a/assets/outputs/json/unicode.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "plane0": "Ծ", - "plane1": "𐔔", - "plane2": "𫝼", - "plane3": "𱁬" -} diff --git a/assets/outputs/json/value_after_table.json b/assets/outputs/json/value_after_table.json deleted file mode 100644 index 93e0fd7..0000000 --- a/assets/outputs/json/value_after_table.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "foo": {}, - "qux": true -} diff --git a/assets/outputs/json/very_compact.json b/assets/outputs/json/very_compact.json deleted file mode 100644 index 65ecfe0..0000000 --- a/assets/outputs/json/very_compact.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "one": { - "foo": "bar", - "bar": "foo" - }, - "two": { - "foo": 1, - "bar": 2 - }, - "three": { - "foo": 1.0, - "bar": 2.0 - }, - "four": { - "foo": true, - "bar": false - }, - "five": { - "foo": null, - "bar": null - }, - "six": { - "foo": {}, - "bar": {} - }, - "seven": { - "foo": [], - "bar": [] - }, - "eight": [ - "foo", - "bar" - ], - "nine": [ - true, - false - ], - "ten": [ - 1, - 2 - ], - "eleven": [ - [], - [] - ], - "twelve": [ - {}, - {} - ] -} diff --git a/assets/outputs/toml/array.toml b/assets/outputs/toml/array.toml deleted file mode 100644 index 93915c9..0000000 --- a/assets/outputs/toml/array.toml +++ /dev/null @@ -1,6 +0,0 @@ -foo = [ - 1, - 2, - 3, -] - diff --git a/assets/outputs/toml/basic.toml b/assets/outputs/toml/basic.toml deleted file mode 100644 index ff8cd1f..0000000 --- a/assets/outputs/toml/basic.toml +++ /dev/null @@ -1,2 +0,0 @@ -foo = "bar" - diff --git a/assets/outputs/toml/basic_empty_let.toml b/assets/outputs/toml/basic_empty_let.toml deleted file mode 100644 index ff8cd1f..0000000 --- a/assets/outputs/toml/basic_empty_let.toml +++ /dev/null @@ -1,2 +0,0 @@ -foo = "bar" - diff --git a/assets/outputs/toml/boolean.toml b/assets/outputs/toml/boolean.toml deleted file mode 100644 index f1e8d97..0000000 --- a/assets/outputs/toml/boolean.toml +++ /dev/null @@ -1,3 +0,0 @@ -foo = true -bar = false - diff --git a/assets/outputs/toml/chained.toml b/assets/outputs/toml/chained.toml deleted file mode 100644 index 541b786..0000000 --- a/assets/outputs/toml/chained.toml +++ /dev/null @@ -1,3 +0,0 @@ -[foo] -bar = "baz" - diff --git a/assets/outputs/toml/chained_complex.toml b/assets/outputs/toml/chained_complex.toml deleted file mode 100644 index e488a75..0000000 --- a/assets/outputs/toml/chained_complex.toml +++ /dev/null @@ -1,10 +0,0 @@ -[foo] -qux = true -quux = [ - "green eggs", - "ham", -] - -[foo.bar] -baz = 42 - diff --git a/assets/outputs/toml/char.toml b/assets/outputs/toml/char.toml deleted file mode 100644 index bf0fbaa..0000000 --- a/assets/outputs/toml/char.toml +++ /dev/null @@ -1,2 +0,0 @@ -foo = "a" - diff --git a/assets/outputs/toml/comment.toml b/assets/outputs/toml/comment.toml deleted file mode 100644 index ff8cd1f..0000000 --- a/assets/outputs/toml/comment.toml +++ /dev/null @@ -1,2 +0,0 @@ -foo = "bar" - diff --git a/assets/outputs/toml/compact.toml b/assets/outputs/toml/compact.toml deleted file mode 100644 index 0d9cd8d..0000000 --- a/assets/outputs/toml/compact.toml +++ /dev/null @@ -1,47 +0,0 @@ -eight = [ - "foo", - "bar", -] -nine = [ - true, - false, -] -ten = [ - 1, - 2, -] -eleven = [ - [], - [], -] - -[one] -foo = "bar" -bar = "foo" - -[two] -foo = 1 -bar = 2 - -[three] -foo = 1.0 -bar = 2.0 - -[four] -foo = true -bar = false - -[five] - -[six.foo] - -[six.bar] - -[seven] -foo = [] -bar = [] - -[[twelve]] - -[[twelve]] - diff --git a/assets/outputs/toml/complex.toml b/assets/outputs/toml/complex.toml deleted file mode 100644 index 2717888..0000000 --- a/assets/outputs/toml/complex.toml +++ /dev/null @@ -1,34 +0,0 @@ -age = 32 -gender = "M" -favourites = [ - "blue", - "fish", - "egg", - "Postman", - 4.73753, - false, - { hello = "world", food = { favourite = "egg", hated = "beef" } }, -] -empty2 = [] - -[name] -first = "John" -last = "Smith" -full = "John Smith" - -[employment] -employed = true -name = "Postman" -sinceYear = 2019 - -[parents.father.birthday] -year = 1970 -month = 2 -day = 3 - -[empty1] - -[negative] -int = -34 -float = -34.34 - diff --git a/assets/outputs/toml/complex_keys.toml b/assets/outputs/toml/complex_keys.toml deleted file mode 100644 index 4647d38..0000000 --- a/assets/outputs/toml/complex_keys.toml +++ /dev/null @@ -1,12 +0,0 @@ -with_underscore = 0 -with-dash = 1 -"with_🌽" = 2 -"!£$%^&*()_" = 3 -j12345 = 4 - -[foo] -bar-baz = "hello" - -[apple-pie] -crust = "yum" - diff --git a/assets/outputs/toml/environment_variable.toml b/assets/outputs/toml/environment_variable.toml deleted file mode 100644 index ff8cd1f..0000000 --- a/assets/outputs/toml/environment_variable.toml +++ /dev/null @@ -1,2 +0,0 @@ -foo = "bar" - diff --git a/assets/outputs/toml/float.toml b/assets/outputs/toml/float.toml deleted file mode 100644 index a8152ce..0000000 --- a/assets/outputs/toml/float.toml +++ /dev/null @@ -1,3 +0,0 @@ -foo = 3.14159 -bar = 101.0 - diff --git a/assets/outputs/toml/input.toml b/assets/outputs/toml/input.toml deleted file mode 100644 index 8edd9bf..0000000 --- a/assets/outputs/toml/input.toml +++ /dev/null @@ -1,9 +0,0 @@ -[name] -first = "John" -last = "Smith" - -[dob] -day = 1 -month = 1 -year = 1970 - diff --git a/assets/outputs/toml/input_references_input.toml b/assets/outputs/toml/input_references_input.toml deleted file mode 100644 index ff8cd1f..0000000 --- a/assets/outputs/toml/input_references_input.toml +++ /dev/null @@ -1,2 +0,0 @@ -foo = "bar" - diff --git a/assets/outputs/toml/integer.toml b/assets/outputs/toml/integer.toml deleted file mode 100644 index c35536e..0000000 --- a/assets/outputs/toml/integer.toml +++ /dev/null @@ -1,28 +0,0 @@ -positive_decimal = 42 -negative_decimal = -123 -zero = 0 -large_decimal = 1000000 -negative_large_decimal = -1234567 -decimal_with_underscores = 123456 -hex_lowercase = 16448250 -hex_uppercase = 255 -hex_mixed = 11259375 -negative_hex = -2748 -hex_with_underscores = 16448250 -negative_hex_underscores = -11259375 -hex_single_digit = 15 -hex_zero = 0 -octal_basic = 493 -octal_zero = 0 -negative_octal = -83 -octal_with_underscores = 42798 -negative_octal_underscores = -256794 -octal_single_digit = 7 -binary_basic = 10 -binary_zero = 0 -negative_binary = -12 -binary_with_underscores = 2767 -negative_binary_underscores = -195 -binary_single_digit = 1 -binary_all_ones = 15 - diff --git a/assets/outputs/toml/invalid.toml b/assets/outputs/toml/invalid.toml deleted file mode 100644 index e69de29..0000000 diff --git a/assets/outputs/toml/invalid_input.toml b/assets/outputs/toml/invalid_input.toml deleted file mode 100644 index e69de29..0000000 diff --git a/assets/outputs/toml/invalid_nesting.toml b/assets/outputs/toml/invalid_nesting.toml deleted file mode 100644 index e69de29..0000000 diff --git a/assets/outputs/toml/invalid_spread.toml b/assets/outputs/toml/invalid_spread.toml deleted file mode 100644 index e69de29..0000000 diff --git a/assets/outputs/toml/mixed_array.toml b/assets/outputs/toml/mixed_array.toml deleted file mode 100644 index 8ef2495..0000000 --- a/assets/outputs/toml/mixed_array.toml +++ /dev/null @@ -1,6 +0,0 @@ -foo = [ - 1, - "two", - false, -] - diff --git a/assets/outputs/toml/null.toml b/assets/outputs/toml/null.toml deleted file mode 100644 index 8b13789..0000000 --- a/assets/outputs/toml/null.toml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/assets/outputs/toml/null_in_array.toml b/assets/outputs/toml/null_in_array.toml deleted file mode 100644 index e69de29..0000000 diff --git a/assets/outputs/toml/object.toml b/assets/outputs/toml/object.toml deleted file mode 100644 index cb098b5..0000000 --- a/assets/outputs/toml/object.toml +++ /dev/null @@ -1,3 +0,0 @@ -[foo] -bar = 42 - diff --git a/assets/outputs/toml/object_in_array.toml b/assets/outputs/toml/object_in_array.toml deleted file mode 100644 index 0bdcc24..0000000 --- a/assets/outputs/toml/object_in_array.toml +++ /dev/null @@ -1,4 +0,0 @@ -[[foo]] -foo = 1 -bar = 2 - diff --git a/assets/outputs/toml/quoted_keys.toml b/assets/outputs/toml/quoted_keys.toml deleted file mode 100644 index d95a19d..0000000 --- a/assets/outputs/toml/quoted_keys.toml +++ /dev/null @@ -1,9 +0,0 @@ -"foo.bar" = 42 -"with spaces" = true -"escaped'quote" = false -"escaped=equals" = -3 -'normal"quotes' = "funny" - -["green.eggs".and] -ham = "hello world" - diff --git a/assets/outputs/toml/readme_example.toml b/assets/outputs/toml/readme_example.toml deleted file mode 100644 index 04bcc5d..0000000 --- a/assets/outputs/toml/readme_example.toml +++ /dev/null @@ -1,30 +0,0 @@ -name = "example-package" -version = "1.0.0" -main = "dist/index.js" -private = false - -[bin] -filebrowser = "dist/index.js" - -[author] -name = "John Smith" -email = "mail@example.com" -url = "https://example.com" - -[[contributors]] -name = "John Smith" -email = "mail@example.com" - -[scripts] -build = "tsc" -run = "node dist" - -[dependencies] -dotenv = "^8.2.0" - -[devDependencies] -typescript = "^4.5" - -[config] -port = 8080 - diff --git a/assets/outputs/toml/spread.toml b/assets/outputs/toml/spread.toml deleted file mode 100644 index c7fd933..0000000 --- a/assets/outputs/toml/spread.toml +++ /dev/null @@ -1,9 +0,0 @@ -hello = "world" -bar = "baz" -nums = [ - 1, - 2, - 3, - 4, -] - diff --git a/assets/outputs/toml/string.toml b/assets/outputs/toml/string.toml deleted file mode 100644 index 233fbf6..0000000 --- a/assets/outputs/toml/string.toml +++ /dev/null @@ -1,7 +0,0 @@ -foo = "bar" -bar = """ -"\\ -\r\t""" -baz = "a" -qux = "" - diff --git a/assets/outputs/toml/string_interpolation.toml b/assets/outputs/toml/string_interpolation.toml deleted file mode 100644 index f359285..0000000 --- a/assets/outputs/toml/string_interpolation.toml +++ /dev/null @@ -1,3 +0,0 @@ -foo = "hello, world" -bar = "$escaped" - diff --git a/assets/outputs/toml/string_multiline.toml b/assets/outputs/toml/string_multiline.toml deleted file mode 100644 index d2a49da..0000000 --- a/assets/outputs/toml/string_multiline.toml +++ /dev/null @@ -1,5 +0,0 @@ -foo = """ -hello -world -""" - diff --git a/assets/outputs/toml/unicode.toml b/assets/outputs/toml/unicode.toml deleted file mode 100644 index 98cf61f..0000000 --- a/assets/outputs/toml/unicode.toml +++ /dev/null @@ -1,5 +0,0 @@ -plane0 = "Ծ" -plane1 = "𐔔" -plane2 = "𫝼" -plane3 = "𱁬" - diff --git a/assets/outputs/toml/value_after_table.toml b/assets/outputs/toml/value_after_table.toml deleted file mode 100644 index 26b3e99..0000000 --- a/assets/outputs/toml/value_after_table.toml +++ /dev/null @@ -1,4 +0,0 @@ -qux = true - -[foo] - diff --git a/assets/outputs/toml/very_compact.toml b/assets/outputs/toml/very_compact.toml deleted file mode 100644 index 0d9cd8d..0000000 --- a/assets/outputs/toml/very_compact.toml +++ /dev/null @@ -1,47 +0,0 @@ -eight = [ - "foo", - "bar", -] -nine = [ - true, - false, -] -ten = [ - 1, - 2, -] -eleven = [ - [], - [], -] - -[one] -foo = "bar" -bar = "foo" - -[two] -foo = 1 -bar = 2 - -[three] -foo = 1.0 -bar = 2.0 - -[four] -foo = true -bar = false - -[five] - -[six.foo] - -[six.bar] - -[seven] -foo = [] -bar = [] - -[[twelve]] - -[[twelve]] - diff --git a/assets/outputs/yaml/array.yml b/assets/outputs/yaml/array.yml deleted file mode 100644 index bd735ce..0000000 --- a/assets/outputs/yaml/array.yml +++ /dev/null @@ -1,5 +0,0 @@ -foo: -- 1 -- 2 -- 3 - diff --git a/assets/outputs/yaml/basic.yml b/assets/outputs/yaml/basic.yml deleted file mode 100644 index 8218b15..0000000 --- a/assets/outputs/yaml/basic.yml +++ /dev/null @@ -1,2 +0,0 @@ -foo: bar - diff --git a/assets/outputs/yaml/basic_empty_let.yml b/assets/outputs/yaml/basic_empty_let.yml deleted file mode 100644 index 8218b15..0000000 --- a/assets/outputs/yaml/basic_empty_let.yml +++ /dev/null @@ -1,2 +0,0 @@ -foo: bar - diff --git a/assets/outputs/yaml/boolean.yml b/assets/outputs/yaml/boolean.yml deleted file mode 100644 index 51803fe..0000000 --- a/assets/outputs/yaml/boolean.yml +++ /dev/null @@ -1,3 +0,0 @@ -foo: true -bar: false - diff --git a/assets/outputs/yaml/chained.yml b/assets/outputs/yaml/chained.yml deleted file mode 100644 index 72e0412..0000000 --- a/assets/outputs/yaml/chained.yml +++ /dev/null @@ -1,3 +0,0 @@ -foo: - bar: baz - diff --git a/assets/outputs/yaml/chained_complex.yml b/assets/outputs/yaml/chained_complex.yml deleted file mode 100644 index 60d173c..0000000 --- a/assets/outputs/yaml/chained_complex.yml +++ /dev/null @@ -1,8 +0,0 @@ -foo: - bar: - baz: 42 - qux: true - quux: - - green eggs - - ham - diff --git a/assets/outputs/yaml/char.yml b/assets/outputs/yaml/char.yml deleted file mode 100644 index 8445b0e..0000000 --- a/assets/outputs/yaml/char.yml +++ /dev/null @@ -1,2 +0,0 @@ -foo: a - diff --git a/assets/outputs/yaml/comment.yml b/assets/outputs/yaml/comment.yml deleted file mode 100644 index 8218b15..0000000 --- a/assets/outputs/yaml/comment.yml +++ /dev/null @@ -1,2 +0,0 @@ -foo: bar - diff --git a/assets/outputs/yaml/compact.yml b/assets/outputs/yaml/compact.yml deleted file mode 100644 index ada8415..0000000 --- a/assets/outputs/yaml/compact.yml +++ /dev/null @@ -1,37 +0,0 @@ -one: - foo: bar - bar: foo -two: - foo: 1 - bar: 2 -three: - foo: 1.0 - bar: 2.0 -four: - foo: true - bar: false -five: - foo: null - bar: null -six: - foo: {} - bar: {} -seven: - foo: [] - bar: [] -eight: -- foo -- bar -nine: -- true -- false -ten: -- 1 -- 2 -eleven: -- [] -- [] -twelve: -- {} -- {} - diff --git a/assets/outputs/yaml/complex.yml b/assets/outputs/yaml/complex.yml deleted file mode 100644 index 1c34547..0000000 --- a/assets/outputs/yaml/complex.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: - first: John - last: Smith - full: John Smith -age: 32 -employment: - employed: true - name: Postman - sinceYear: 2019 -placeholder: null -parents: - father: - birthday: - year: 1970 - month: 2 - day: 3 -gender: M -favourites: -- blue -- fish -- egg -- Postman -- 4.73753 -- false -- hello: world - food: - favourite: egg - hated: beef -empty1: {} -empty2: [] -negative: - int: -34 - float: -34.34 - diff --git a/assets/outputs/yaml/complex_keys.yml b/assets/outputs/yaml/complex_keys.yml deleted file mode 100644 index 24d3214..0000000 --- a/assets/outputs/yaml/complex_keys.yml +++ /dev/null @@ -1,10 +0,0 @@ -with_underscore: 0 -with-dash: 1 -with_🌽: 2 -'!£$%^&*()_': 3 -j12345: 4 -foo: - bar-baz: hello -apple-pie: - crust: yum - diff --git a/assets/outputs/yaml/environment_variable.yml b/assets/outputs/yaml/environment_variable.yml deleted file mode 100644 index 8218b15..0000000 --- a/assets/outputs/yaml/environment_variable.yml +++ /dev/null @@ -1,2 +0,0 @@ -foo: bar - diff --git a/assets/outputs/yaml/float.yml b/assets/outputs/yaml/float.yml deleted file mode 100644 index fc333c1..0000000 --- a/assets/outputs/yaml/float.yml +++ /dev/null @@ -1,3 +0,0 @@ -foo: 3.14159 -bar: 101.0 - diff --git a/assets/outputs/yaml/input.yml b/assets/outputs/yaml/input.yml deleted file mode 100644 index ae8d162..0000000 --- a/assets/outputs/yaml/input.yml +++ /dev/null @@ -1,8 +0,0 @@ -name: - first: John - last: Smith -dob: - day: 1 - month: 1 - year: 1970 - diff --git a/assets/outputs/yaml/input_references_input.yml b/assets/outputs/yaml/input_references_input.yml deleted file mode 100644 index 8218b15..0000000 --- a/assets/outputs/yaml/input_references_input.yml +++ /dev/null @@ -1,2 +0,0 @@ -foo: bar - diff --git a/assets/outputs/yaml/integer.yml b/assets/outputs/yaml/integer.yml deleted file mode 100644 index f2d1400..0000000 --- a/assets/outputs/yaml/integer.yml +++ /dev/null @@ -1,28 +0,0 @@ -positive_decimal: 42 -negative_decimal: -123 -zero: 0 -large_decimal: 1000000 -negative_large_decimal: -1234567 -decimal_with_underscores: 123456 -hex_lowercase: 16448250 -hex_uppercase: 255 -hex_mixed: 11259375 -negative_hex: -2748 -hex_with_underscores: 16448250 -negative_hex_underscores: -11259375 -hex_single_digit: 15 -hex_zero: 0 -octal_basic: 493 -octal_zero: 0 -negative_octal: -83 -octal_with_underscores: 42798 -negative_octal_underscores: -256794 -octal_single_digit: 7 -binary_basic: 10 -binary_zero: 0 -negative_binary: -12 -binary_with_underscores: 2767 -negative_binary_underscores: -195 -binary_single_digit: 1 -binary_all_ones: 15 - diff --git a/assets/outputs/yaml/invalid.yml b/assets/outputs/yaml/invalid.yml deleted file mode 100644 index e69de29..0000000 diff --git a/assets/outputs/yaml/invalid_input.yml b/assets/outputs/yaml/invalid_input.yml deleted file mode 100644 index e69de29..0000000 diff --git a/assets/outputs/yaml/invalid_nesting.yml b/assets/outputs/yaml/invalid_nesting.yml deleted file mode 100644 index e69de29..0000000 diff --git a/assets/outputs/yaml/invalid_spread.yml b/assets/outputs/yaml/invalid_spread.yml deleted file mode 100644 index e69de29..0000000 diff --git a/assets/outputs/yaml/mixed_array.yml b/assets/outputs/yaml/mixed_array.yml deleted file mode 100644 index 4f6aead..0000000 --- a/assets/outputs/yaml/mixed_array.yml +++ /dev/null @@ -1,5 +0,0 @@ -foo: -- 1 -- two -- false - diff --git a/assets/outputs/yaml/null.yml b/assets/outputs/yaml/null.yml deleted file mode 100644 index 1e30655..0000000 --- a/assets/outputs/yaml/null.yml +++ /dev/null @@ -1,2 +0,0 @@ -foo: null - diff --git a/assets/outputs/yaml/null_in_array.yml b/assets/outputs/yaml/null_in_array.yml deleted file mode 100644 index 74c12c9..0000000 --- a/assets/outputs/yaml/null_in_array.yml +++ /dev/null @@ -1,3 +0,0 @@ -foo: -- null - diff --git a/assets/outputs/yaml/object.yml b/assets/outputs/yaml/object.yml deleted file mode 100644 index 5c3430e..0000000 --- a/assets/outputs/yaml/object.yml +++ /dev/null @@ -1,3 +0,0 @@ -foo: - bar: 42 - diff --git a/assets/outputs/yaml/object_in_array.yml b/assets/outputs/yaml/object_in_array.yml deleted file mode 100644 index 59808f2..0000000 --- a/assets/outputs/yaml/object_in_array.yml +++ /dev/null @@ -1,4 +0,0 @@ -foo: -- foo: 1 - bar: 2 - diff --git a/assets/outputs/yaml/quoted_keys.yml b/assets/outputs/yaml/quoted_keys.yml deleted file mode 100644 index 8172c2d..0000000 --- a/assets/outputs/yaml/quoted_keys.yml +++ /dev/null @@ -1,9 +0,0 @@ -foo.bar: 42 -green.eggs: - and: - ham: hello world -with spaces: true -escaped'quote: false -escaped=equals: -3 -normal"quotes: funny - diff --git a/assets/outputs/yaml/readme_example.yml b/assets/outputs/yaml/readme_example.yml deleted file mode 100644 index 423d613..0000000 --- a/assets/outputs/yaml/readme_example.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: example-package -version: 1.0.0 -main: dist/index.js -bin: - filebrowser: dist/index.js -private: false -author: - name: John Smith - email: mail@example.com - url: https://example.com -contributors: -- name: John Smith - email: mail@example.com -scripts: - build: tsc - run: node dist -dependencies: - dotenv: ^8.2.0 -devDependencies: - typescript: ^4.5 -config: - port: 8080 - hostname: null - diff --git a/assets/outputs/yaml/spread.yml b/assets/outputs/yaml/spread.yml deleted file mode 100644 index ca39fc1..0000000 --- a/assets/outputs/yaml/spread.yml +++ /dev/null @@ -1,8 +0,0 @@ -hello: world -bar: baz -nums: -- 1 -- 2 -- 3 -- 4 - diff --git a/assets/outputs/yaml/string.yml b/assets/outputs/yaml/string.yml deleted file mode 100644 index 6a78af1..0000000 --- a/assets/outputs/yaml/string.yml +++ /dev/null @@ -1,5 +0,0 @@ -foo: bar -bar: "\"\\\n\r\t" -baz: a -qux: '' - diff --git a/assets/outputs/yaml/string_interpolation.yml b/assets/outputs/yaml/string_interpolation.yml deleted file mode 100644 index 85e84ed..0000000 --- a/assets/outputs/yaml/string_interpolation.yml +++ /dev/null @@ -1,3 +0,0 @@ -foo: hello, world -bar: $escaped - diff --git a/assets/outputs/yaml/string_multiline.yml b/assets/outputs/yaml/string_multiline.yml deleted file mode 100644 index 58f9fac..0000000 --- a/assets/outputs/yaml/string_multiline.yml +++ /dev/null @@ -1,4 +0,0 @@ -foo: | - hello - world - diff --git a/assets/outputs/yaml/unicode.yml b/assets/outputs/yaml/unicode.yml deleted file mode 100644 index d53844d..0000000 --- a/assets/outputs/yaml/unicode.yml +++ /dev/null @@ -1,5 +0,0 @@ -plane0: Ծ -plane1: 𐔔 -plane2: 𫝼 -plane3: 𱁬 - diff --git a/assets/outputs/yaml/value_after_table.yml b/assets/outputs/yaml/value_after_table.yml deleted file mode 100644 index d8760a5..0000000 --- a/assets/outputs/yaml/value_after_table.yml +++ /dev/null @@ -1,3 +0,0 @@ -foo: {} -qux: true - diff --git a/assets/outputs/yaml/very_compact.yml b/assets/outputs/yaml/very_compact.yml deleted file mode 100644 index ada8415..0000000 --- a/assets/outputs/yaml/very_compact.yml +++ /dev/null @@ -1,37 +0,0 @@ -one: - foo: bar - bar: foo -two: - foo: 1 - bar: 2 -three: - foo: 1.0 - bar: 2.0 -four: - foo: true - bar: false -five: - foo: null - bar: null -six: - foo: {} - bar: {} -seven: - foo: [] - bar: [] -eight: -- foo -- bar -nine: -- true -- false -ten: -- 1 -- 2 -eleven: -- [] -- [] -twelve: -- {} -- {} - diff --git a/benches/serde.rs b/benches/serde.rs deleted file mode 100644 index ad2227a..0000000 --- a/benches/serde.rs +++ /dev/null @@ -1,453 +0,0 @@ -use criterion::{Criterion, Throughput, criterion_group, criterion_main}; -use serde::Deserialize; -use std::hint::black_box; - -#[derive(Deserialize, Debug, PartialEq)] -struct Empty {} - -#[derive(Deserialize, Debug, PartialEq)] -struct Array { - foo: Vec, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Basic { - foo: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -#[serde(rename_all = "snake_case")] -enum BasicNewTypeEnum { - Foo(String), -} - -#[derive(Deserialize, Debug, PartialEq)] -struct BasicUnitEnum { - foo: BasicUnitEnumInner, -} - -#[derive(Deserialize, Debug, PartialEq)] -#[serde(rename_all = "snake_case")] -enum BasicUnitEnumInner { - Bar, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct BasicNewType { - foo: BasicNewTypeInner, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct BasicNewTypeInner(String); - -#[derive(Deserialize, Debug, PartialEq)] -struct Boolean { - foo: bool, - bar: bool, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Bytes<'a> { - foo: &'a [u8], -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Chained { - foo: ChainedInner, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ChainedInner { - bar: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -#[serde(rename_all = "snake_case")] -enum ChainedEnum { - Foo { bar: String }, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ChainedComplex { - foo: ChainedComplexInner, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ChainedComplexInner { - bar: ChainedComplexInnerInner, - qux: bool, - quux: Vec, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ChainedComplexInnerInner { - baz: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Char { - foo: char, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Compact { - one: CompactOne, - two: CompactTwo, - three: CompactThree, - four: CompactFour, - five: CompactFive, - six: CompactSix, - seven: CompactSeven, - eight: Vec, - nine: Vec, - ten: Vec<()>, - eleven: Vec>, - twelve: Vec, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct CompactOne { - foo: String, - bar: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct CompactTwo { - foo: i64, - bar: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct CompactThree { - foo: f64, - bar: f64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct CompactFour { - foo: bool, - bar: bool, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct CompactFive { - foo: (), - bar: (), -} - -#[derive(Deserialize, Debug, PartialEq)] -struct CompactSix { - foo: Empty, - bar: Empty, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct CompactSeven { - foo: Vec, - bar: Vec, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Complex { - age: i64, - employment: ComplexEmployment, - empty1: Empty, - empty2: Vec, - favourites: (String, String, String, String, f64, bool, Favourites), - gender: String, - name: ComplexName, - negative: ComplexNegative, - parents: ComplexParents, - placeholder: (), -} - -#[derive(Deserialize, Debug, PartialEq)] -#[serde(rename_all = "camelCase")] -struct ComplexEmployment { - employed: bool, - name: String, - since_year: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Favourites { - food: ComplexFavouritesFood, - hello: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexFavouritesFood { - favourite: String, - hated: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexName { - first: String, - full: String, - last: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexNegative { - float: f64, - int: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexParents { - father: ComplexParentsFather, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexParentsFather { - birthday: ComplexParentsFatherBirthday, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexParentsFatherBirthday { - day: i64, - month: i64, - year: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexKeys { - #[serde(rename = "!£$%^&*()_")] - symbols: i64, - #[serde(rename = "apple-pie")] - apple_pie: ComplexKeysApplePie, - foo: ComplexKeysFoo, - j12345: i64, - #[serde(rename = "with-dash")] - with_dash: i64, - #[serde(rename = "with_underscore")] - with_underscore: i64, - #[serde(rename = "with_🌽")] - with_corn_emoji: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexKeysApplePie { - crust: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexKeysFoo { - #[serde(rename = "bar-baz")] - bar_baz: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Float { - foo: f64, - bar: f64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Input { - name: InputName, - dob: InputDob, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct InputName { - first: String, - last: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct InputDob { - day: u8, - month: u8, - year: u16, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Integer { - foo: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct MixedArray { - foo: (u8, String, bool), -} - -#[derive(Deserialize, Debug, PartialEq)] -#[serde(rename_all = "snake_case")] -enum MixedArrayEnum { - Foo(u8, String, bool), -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Null { - foo: (), -} - -#[derive(Deserialize, Debug, PartialEq)] -struct NullOption { - foo: Option, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct NullUnit { - foo: NullUnitInner, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct NullUnitInner; - -#[derive(Deserialize, Debug, PartialEq)] -struct Object { - foo: SubObject, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct SubObject { - bar: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ObjectInArray { - foo: Vec, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ObjectInArrayFoo { - bar: i64, - foo: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -#[serde(rename_all = "camelCase")] -struct ReadmeExample { - author: ReadmeExampleAuthor, - bin: ReadmeExampleBin, - config: ReadmeExampleConfig, - contributors: Vec, - dependencies: ReadmeExampleDependencies, - dev_dependencies: ReadmeExampleDevDependencies, - main: String, - name: String, - private: bool, - scripts: ReadmeExampleScripts, - version: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct String_ { - foo: String, - bar: String, - baz: String, - qux: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ReadmeExampleAuthor { - email: String, - name: String, - url: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ReadmeExampleBin { - filebrowser: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ReadmeExampleConfig { - hostname: Option, - port: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ReadmeExampleContributor { - email: String, - name: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ReadmeExampleDependencies { - dotenv: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ReadmeExampleDevDependencies { - typescript: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ReadmeExampleScripts { - build: String, - run: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Str<'a> { - foo: &'a str, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ValueAfterTable { - foo: Empty, - qux: bool, -} - -macro_rules! bench_case { - ($group:expr, $name:literal, $input_file:literal, $output_type:ty) => { - let input = include_str!(concat!("../assets/inputs/", $input_file, ".corn")); - $group.throughput(Throughput::Bytes(input.len() as u64)); - $group.bench_function($name, |b| { - b.iter(|| { - let result: Result<$output_type, _> = corn::from_str(black_box(input)); - black_box(result.unwrap()) - }) - }); - }; -} - -fn criterion_benchmark(c: &mut Criterion) { - let mut group = c.benchmark_group("corn_parsing"); - group.sample_size(500); - - bench_case!(group, "array", "array", Array); - bench_case!(group, "basic", "basic", Basic); - bench_case!(group, "basic_empty_let", "basic_empty_let", Basic); - bench_case!(group, "boolean", "boolean", Boolean); - bench_case!(group, "chained", "chained", Chained); - bench_case!(group, "chained_complex", "chained_complex", ChainedComplex); - bench_case!(group, "char", "char", Char); - bench_case!(group, "comment", "comment", Basic); - bench_case!(group, "compact", "compact", Compact); - bench_case!(group, "complex", "complex", Complex); - bench_case!(group, "complex_keys", "complex_keys", ComplexKeys); - bench_case!(group, "environment_variable", "environment_variable", Basic); - bench_case!(group, "float", "float", Float); - bench_case!(group, "input", "input", Input); - bench_case!( - group, - "input_references_input", - "input_references_input", - Basic - ); - bench_case!(group, "integer", "integer", Integer); - bench_case!(group, "mixed_array", "mixed_array", MixedArray); - bench_case!(group, "null", "null", Null); - bench_case!(group, "object", "object", Object); - bench_case!(group, "object_in_array", "object_in_array", ObjectInArray); - bench_case!(group, "readme_example", "readme_example", ReadmeExample); - bench_case!(group, "string", "string", String_); - bench_case!(group, "string_interpolation", "string_interpolation", Basic); - bench_case!( - group, - "value_after_table", - "value_after_table", - ValueAfterTable - ); - bench_case!(group, "very_compact", "very_compact", Compact); - - group.finish(); -} - -criterion_group!(benches, criterion_benchmark); -criterion_main!(benches); diff --git a/tests/borrowed_tests.rs b/tests/borrowed_tests.rs deleted file mode 100644 index 1fc04bc..0000000 --- a/tests/borrowed_tests.rs +++ /dev/null @@ -1,191 +0,0 @@ -use corn::from_str; -use serde::Deserialize; -use std::borrow::Cow; -use std::fs; - -// Borrowed structure for basic string test -#[derive(Deserialize, Debug, PartialEq)] -struct BorrowedBasic<'a> { - #[serde(borrow)] - foo: Cow<'a, str>, -} - -// Borrowed structure for string test with multiple fields -#[derive(Deserialize, Debug, PartialEq)] -struct BorrowedString<'a> { - #[serde(borrow)] - foo: Cow<'a, str>, - #[serde(borrow)] - bar: Cow<'a, str>, - #[serde(borrow)] - baz: Cow<'a, str>, - #[serde(borrow)] - qux: Cow<'a, str>, -} - -// Borrowed structure using Cow for flexible ownership -#[derive(Deserialize, Debug, PartialEq)] -struct BorrowedStringCow<'a> { - #[serde(borrow)] - foo: Cow<'a, str>, - #[serde(borrow)] - bar: Cow<'a, str>, - #[serde(borrow)] - baz: Cow<'a, str>, - #[serde(borrow)] - qux: Cow<'a, str>, -} - -// Borrowed nested structure -#[derive(Deserialize, Debug, PartialEq)] -struct BorrowedNested<'a> { - #[serde(borrow)] - name: BorrowedName<'a>, - age: i64, - #[serde(borrow)] - gender: Cow<'a, str>, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct BorrowedName<'a> { - #[serde(borrow)] - first: Cow<'a, str>, - #[serde(borrow)] - last: Cow<'a, str>, - #[serde(borrow)] - full: Cow<'a, str>, -} - -// Mixed borrowed and owned fields -#[derive(Deserialize, Debug, PartialEq)] -struct BorrowedMixed<'a> { - #[serde(borrow)] - name: BorrowedNameMixed<'a>, - age: i64, - employment: BorrowedEmployment<'a>, - #[serde(borrow)] - gender: Cow<'a, str>, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct BorrowedNameMixed<'a> { - #[serde(borrow)] - first: Cow<'a, str>, - #[serde(borrow)] - last: Cow<'a, str>, - // full name might be interpolated, so we use Cow - #[serde(borrow)] - full: Cow<'a, str>, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct BorrowedEmployment<'a> { - employed: bool, - #[serde(borrow)] - name: Cow<'a, str>, - #[serde(rename = "sinceYear")] - since_year: i64, -} - -#[test] -fn test_borrowed_basic() { - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/basic.corn")).unwrap(); - - let config: BorrowedBasic = from_str(&input).unwrap(); - - assert_eq!(config.foo, "bar"); -} - -#[test] -fn test_borrowed_string() { - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/string.corn")).unwrap(); - - let config: BorrowedString = from_str(&input).unwrap(); - - assert_eq!(config.foo, "bar"); - assert_eq!(config.bar, "\"\\\n\r\t"); - assert_eq!(config.baz, "a"); // Unicode escape \u{0061} - assert_eq!(config.qux, ""); -} - -#[test] -fn test_borrowed_string_cow() { - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/string.corn")).unwrap(); - - let config: BorrowedStringCow = from_str(&input).unwrap(); - - assert_eq!(config.foo, "bar"); - assert_eq!(config.bar, "\"\\\n\r\t"); - assert_eq!(config.baz, "a"); - assert_eq!(config.qux, ""); -} - -#[test] -fn test_borrowed_nested() { - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/complex.corn")).unwrap(); - - let config: BorrowedNested = from_str(&input).unwrap(); - - assert_eq!(config.name.first, "John"); - assert_eq!(config.name.last, "Smith"); - assert_eq!(config.name.full, "John Smith"); - assert_eq!(config.age, 32); - assert_eq!(config.gender, "M"); -} - -#[test] -fn test_borrowed_mixed() { - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/complex.corn")).unwrap(); - - let config: BorrowedMixed = from_str(&input).unwrap(); - - assert_eq!(config.name.first, "John"); - assert_eq!(config.name.last, "Smith"); - assert_eq!(config.name.full, "John Smith"); - assert_eq!(config.age, 32); - assert!(config.employment.employed); - assert_eq!(config.employment.name, "Postman"); - assert_eq!(config.employment.since_year, 2019); - assert_eq!(config.gender, "M"); -} - -// Test that demonstrates zero-copy behavior with lifetime constraints -#[test] -fn test_borrowed_lifetime_constraint() { - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/basic.corn")).unwrap(); - - let config: BorrowedBasic; - - { - config = from_str(&input).unwrap(); - assert_eq!(config.foo, "bar"); - } - - // config can still be used here because input is still alive - assert_eq!(config.foo, "bar"); -} - -// Test array with borrowed string elements -#[derive(Deserialize, Debug, PartialEq)] -struct BorrowedArray<'a> { - #[serde(borrow)] - foo: Vec>, -} - -#[test] -fn test_borrowed_array() { - let test_input = r#"{ foo = ["hello" "world" "test"] }"#; - - let config: BorrowedArray = from_str(test_input).unwrap(); - - assert_eq!(config.foo.len(), 3); - assert_eq!(config.foo[0], "hello"); - assert_eq!(config.foo[1], "world"); - assert_eq!(config.foo[2], "test"); -} diff --git a/tests/de_tests.rs b/tests/de_tests.rs deleted file mode 100644 index a337801..0000000 --- a/tests/de_tests.rs +++ /dev/null @@ -1,652 +0,0 @@ -use corn::from_str; -use paste::paste; -use serde::Deserialize; -use std::fs; - -macro_rules! generate_eq_tests { - ($(($test_name:ident, $test_type:ty)),+) => { - $( - paste! { - #[test] - fn $test_name() { - let test_name = stringify!($test_name); - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::<$test_type>(&input).unwrap(); - - let json_input = fs::read_to_string(format!("{root_dir}/assets/outputs/json/{test_name}.json")).unwrap(); - let json_config = serde_json::from_str(&json_input).unwrap(); - - assert_eq!(config, json_config); - } - } - )+ - }; -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Empty {} - -#[derive(Deserialize, Debug, PartialEq)] -struct Array { - foo: Vec, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Basic { - foo: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -#[serde(rename_all = "snake_case")] -enum BasicNewTypeEnum { - Foo(String), -} - -#[derive(Deserialize, Debug, PartialEq)] -struct BasicUnitEnum { - foo: BasicUnitEnumInner, -} - -#[derive(Deserialize, Debug, PartialEq)] -#[serde(rename_all = "snake_case")] -enum BasicUnitEnumInner { - Bar, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct BasicNewType { - foo: BasicNewTypeInner, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct BasicNewTypeInner(String); - -#[derive(Deserialize, Debug, PartialEq)] -struct Boolean { - foo: bool, - bar: bool, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Bytes { - #[serde(with = "serde_bytes")] - foo: Vec, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Chained { - foo: ChainedInner, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ChainedInner { - bar: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -#[serde(rename_all = "snake_case")] -enum ChainedEnum { - Foo { bar: String }, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ChainedComplex { - foo: ChainedComplexInner, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ChainedComplexInner { - bar: ChainedComplexInnerInner, - qux: bool, - quux: Vec, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ChainedComplexInnerInner { - baz: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Char { - foo: char, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Compact { - one: CompactOne, - two: CompactTwo, - three: CompactThree, - four: CompactFour, - five: CompactFive, - six: CompactSix, - seven: CompactSeven, - eight: Vec, - nine: Vec, - ten: (u8, u8), - eleven: Vec>, - twelve: Vec, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct CompactOne { - foo: String, - bar: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct CompactTwo { - foo: i64, - bar: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct CompactThree { - foo: f64, - bar: f64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct CompactFour { - foo: bool, - bar: bool, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct CompactFive { - foo: (), - bar: (), -} - -#[derive(Deserialize, Debug, PartialEq)] -struct CompactSix { - foo: Empty, - bar: Empty, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct CompactSeven { - foo: Vec, - bar: Vec, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Complex { - age: i64, - employment: ComplexEmployment, - empty1: Empty, - empty2: Vec, - favourites: (String, String, String, String, f64, bool, Favourites), - gender: String, - name: ComplexName, - negative: ComplexNegative, - parents: ComplexParents, - placeholder: (), -} - -#[derive(Deserialize, Debug, PartialEq)] -#[serde(rename_all = "camelCase")] -struct ComplexEmployment { - employed: bool, - name: String, - since_year: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Favourites { - food: ComplexFavouritesFood, - hello: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexFavouritesFood { - favourite: String, - hated: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexName { - first: String, - full: String, - last: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexNegative { - float: f64, - int: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexParents { - father: ComplexParentsFather, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexParentsFather { - birthday: ComplexParentsFatherBirthday, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexParentsFatherBirthday { - day: i64, - month: i64, - year: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexKeys { - #[serde(rename = "!£$%^&*()_")] - symbols: i64, - #[serde(rename = "apple-pie")] - apple_pie: ComplexKeysApplePie, - foo: ComplexKeysFoo, - j12345: i64, - #[serde(rename = "with-dash")] - with_dash: i64, - #[serde(rename = "with_underscore")] - with_underscore: i64, - #[serde(rename = "with_🌽")] - with_corn_emoji: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexKeysApplePie { - crust: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ComplexKeysFoo { - #[serde(rename = "bar-baz")] - bar_baz: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Float { - foo: f64, - bar: f64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Input { - name: InputName, - dob: InputDob, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct InputName { - first: String, - last: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct InputDob { - day: u8, - month: u8, - year: u16, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Integer { - // Basic decimal integers - positive_decimal: i64, - negative_decimal: i64, - zero: i64, - - // Decimal with underscores - large_decimal: i64, - negative_large_decimal: i64, - decimal_with_underscores: i64, - - // Hexadecimal integers - hex_lowercase: i64, - hex_uppercase: i64, - hex_mixed: i64, - negative_hex: i64, - hex_with_underscores: i64, - negative_hex_underscores: i64, - hex_single_digit: i64, - hex_zero: i64, - - // Octal integers - octal_basic: i64, - octal_zero: i64, - negative_octal: i64, - octal_with_underscores: i64, - negative_octal_underscores: i64, - octal_single_digit: i64, - - // Binary integers - binary_basic: i64, - binary_zero: i64, - negative_binary: i64, - binary_with_underscores: i64, - negative_binary_underscores: i64, - binary_single_digit: i64, - binary_all_ones: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct MixedArray { - foo: (u8, String, bool), -} - -#[derive(Deserialize, Debug, PartialEq)] -#[serde(rename_all = "snake_case")] -enum MixedArrayEnum { - Foo(u8, String, bool), -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Null { - foo: (), -} - -#[derive(Deserialize, Debug, PartialEq)] -struct NullOption { - foo: Option, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct NullUnit { - foo: NullUnitInner, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct NullUnitInner; - -#[derive(Deserialize, Debug, PartialEq)] -struct NullInArray { - foo: Vec>, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Object { - foo: SubObject, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct SubObject { - bar: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ObjectInArray { - foo: Vec, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ObjectInArrayFoo { - bar: i64, - foo: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -#[serde(rename_all = "camelCase")] -struct ReadmeExample { - author: ReadmeExampleAuthor, - bin: ReadmeExampleBin, - config: ReadmeExampleConfig, - contributors: Vec, - dependencies: ReadmeExampleDependencies, - dev_dependencies: ReadmeExampleDevDependencies, - main: String, - name: String, - private: bool, - scripts: ReadmeExampleScripts, - version: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct QuotedKeys { - #[serde(rename = "foo.bar")] - foo_bar: u8, - #[serde(rename = "green.eggs")] - green_eggs: GreenEggs, - #[serde(rename = "with spaces")] - with_spaces: bool, - #[serde(rename = "escaped'quote")] - escaped_quote: bool, - #[serde(rename = "escaped=equals")] - escaped_equals: i8, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct GreenEggs { - and: And, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct And { - ham: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct String_ { - foo: String, - bar: String, - baz: String, - qux: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ReadmeExampleAuthor { - email: String, - name: String, - url: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ReadmeExampleBin { - filebrowser: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ReadmeExampleConfig { - hostname: Option, - port: i64, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ReadmeExampleContributor { - email: String, - name: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ReadmeExampleDependencies { - dotenv: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ReadmeExampleDevDependencies { - typescript: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ReadmeExampleScripts { - build: String, - run: String, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct ValueAfterTable { - foo: Empty, - qux: bool, -} - -#[derive(Deserialize, Debug, PartialEq)] -struct Unicode { - plane0: String, - plane1: String, - plane2: String, - plane3: String, -} - -generate_eq_tests!( - (array, Array), - (basic, Basic), - (basic_empty_let, Basic), - (boolean, Boolean), - (chained, Chained), - (chained_complex, ChainedComplex), - (char, Char), - (comment, Basic), - (compact, Compact), - (complex, Complex), - (complex_keys, ComplexKeys), - (environment_variable, Basic), - (float, Float), - (input, Input), - (input_references_input, Basic), - (integer, Integer), - (mixed_array, MixedArray), - (null, Null), - (null_in_array, NullInArray), - (object, Object), - (object_in_array, ObjectInArray), - (readme_example, ReadmeExample), - (quoted_keys, QuotedKeys), - (string, String_), - (string_interpolation, Basic), - (value_after_table, ValueAfterTable), - (very_compact, Compact) -); - -// TODO: Several of these can use the macro, tidy - -#[test] -fn basic_new_type_enum() { - let test_name = "basic"; - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input).unwrap(); - - let json_input = - fs::read_to_string(format!("{root_dir}/assets/outputs/json/{test_name}.json")).unwrap(); - let json_config = serde_json::from_str(&json_input).unwrap(); - - assert_eq!(config, json_config); -} - -#[test] -fn basic_unit_enum() { - let test_name = "basic"; - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input).unwrap(); - - let json_input = - fs::read_to_string(format!("{root_dir}/assets/outputs/json/{test_name}.json")).unwrap(); - let json_config = serde_json::from_str(&json_input).unwrap(); - - assert_eq!(config, json_config); -} - -#[test] -fn basic_new_type() { - let test_name = "basic"; - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input).unwrap(); - - let json_input = - fs::read_to_string(format!("{root_dir}/assets/outputs/json/{test_name}.json")).unwrap(); - let json_config = serde_json::from_str(&json_input).unwrap(); - - assert_eq!(config, json_config); -} - -#[test] -fn bytes() { - let test_name = "basic"; - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input).unwrap(); - - let json_input = - fs::read_to_string(format!("{root_dir}/assets/outputs/json/{test_name}.json")).unwrap(); - let json_config = serde_json::from_str(&json_input).unwrap(); - - assert_eq!(config, json_config); -} - -#[test] -fn chained_enum() { - let test_name = "chained"; - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input).unwrap(); - - let json_input = - fs::read_to_string(format!("{root_dir}/assets/outputs/json/{test_name}.json")).unwrap(); - let json_config = serde_json::from_str(&json_input).unwrap(); - - assert_eq!(config, json_config); -} - -#[test] -fn mixed_array_enum() { - let test_name = "mixed_array"; - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input).unwrap(); - - let json_input = - fs::read_to_string(format!("{root_dir}/assets/outputs/json/{test_name}.json")).unwrap(); - let json_config = serde_json::from_str(&json_input).unwrap(); - - assert_eq!(config, json_config); -} - -#[test] -fn null_option() { - let test_name = "null"; - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input).unwrap(); - - let json_input = - fs::read_to_string(format!("{root_dir}/assets/outputs/json/{test_name}.json")).unwrap(); - let json_config = serde_json::from_str(&json_input).unwrap(); - - assert_eq!(config, json_config); -} - -#[test] -fn null_unit() { - let test_name = "null"; - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input).unwrap(); - - let json_input = - fs::read_to_string(format!("{root_dir}/assets/outputs/json/{test_name}.json")).unwrap(); - let json_config = serde_json::from_str(&json_input).unwrap(); - - assert_eq!(config, json_config); -} - -#[test] -fn unicode() { - let test_name = "unicode"; - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input).unwrap(); - - let json_input = - fs::read_to_string(format!("{root_dir}/assets/outputs/json/{test_name}.json")).unwrap(); - let json_config = serde_json::from_str(&json_input).unwrap(); - - assert_eq!(config, json_config); -} diff --git a/tests/parser_tests.rs b/tests/parser_tests.rs deleted file mode 100644 index 4017816..0000000 --- a/tests/parser_tests.rs +++ /dev/null @@ -1,106 +0,0 @@ -use corn::parse; -use paste::paste; -use std::fs; - -macro_rules! generate_eq_tests { - ($($test_name:ident),+) => { - $( - paste!{ - #[test] - fn []() { - let test_name = stringify!($test_name); - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{test_name}.corn")).unwrap(); - let valid = fs::read_to_string(format!("{root_dir}/assets/outputs/json/{test_name}.json")).unwrap().replace("\r", ""); - - let config = parse(input.as_str()).unwrap(); - let serialized = serde_json::to_string_pretty(&config).unwrap().replace("\r", ""); - - assert_eq!(serialized.trim(), valid.trim()); - } - - #[test] - fn []() { - let test_name = stringify!($test_name); - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{test_name}.corn")).unwrap(); - let valid = fs::read_to_string(format!("{root_dir}/assets/outputs/yaml/{test_name}.yml")).unwrap().replace("\r", ""); - - let config = parse(input.as_str()).unwrap(); - let serialized = serde_norway::to_string(&config).unwrap().replace("\r", ""); - - assert_eq!(serialized.trim(), valid.trim()); - } - - #[test] - fn []() { - let test_name = stringify!($test_name); - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{test_name}.corn")).unwrap(); - let valid = fs::read_to_string(format!("{root_dir}/assets/outputs/toml/{test_name}.toml")).unwrap().replace("\r", ""); - - let config = parse(input.as_str()).unwrap(); - // fall back to default as toml can fail due to no null - let serialized = toml_edit::ser::to_string_pretty(&config).unwrap_or_default().replace("\r", ""); - - assert_eq!(serialized.trim(), valid.trim()); - } - } - - )+ - } -} - -macro_rules! generate_invalid_tests { - ($($test_name:ident),+) => { - $( - #[test] - fn $test_name() { - let test_name = stringify!($test_name); - let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - - let input = fs::read_to_string(format!("{root_dir}/assets/inputs/{}.corn", test_name)).unwrap(); - - let config = parse(input.as_str()); - assert!(config.is_err()); - } - )+ - } -} - -generate_eq_tests!( - array, - basic, - basic_empty_let, - boolean, - chained, - chained_complex, - char, - comment, - compact, - complex, - complex_keys, - environment_variable, - float, - input, - input_references_input, - integer, - mixed_array, - null, - null_in_array, - object, - object_in_array, - quoted_keys, - readme_example, - spread, - string, - string_interpolation, - unicode, - value_after_table, - very_compact -); - -generate_invalid_tests!(invalid, invalid_input, invalid_nesting, invalid_spread); diff --git a/tests/test_suite.rs b/tests/test_suite.rs new file mode 100644 index 0000000..ee2f181 --- /dev/null +++ b/tests/test_suite.rs @@ -0,0 +1,32 @@ +use corn::Value as CornValue; +use std::{fs, path::Path}; + +fn positive(path: &Path, content: String) -> datatest_stable::Result<()> { + let json: CornValue = { + let mut path = path.to_path_buf(); + path.set_extension(""); + path.set_extension(""); + path.set_extension("json"); + + let path = Path::new("test-suite/json").join(path.strip_prefix("test-suite/corn/")?); + + serde_json::from_str(&fs::read_to_string(path)?)? + }; + + let corn: CornValue = corn::from_str(&content)?; + + assert_eq!(json, corn); + + Ok(()) +} + +fn negative(_path: &Path, content: String) -> datatest_stable::Result<()> { + assert!(corn::from_str::(&content).is_err()); + + Ok(()) +} + +datatest_stable::harness! { + { test = positive, root = "test-suite", pattern = r"^.*\.pos\.corn$" }, + { test = negative, root = "test-suite", pattern = r"^.*\.neg\.corn$" }, +} From 2b38dc828ff273f9aa06851d07e76c2eaf851565 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Wed, 24 Dec 2025 11:39:38 +0100 Subject: [PATCH 68/68] Remove thiserror for a custom error --- Cargo.lock | 21 --------------------- Cargo.toml | 1 - src/error.rs | 36 ++++++++++++++++++++++++------------ src/lexer.rs | 40 ++++++++++++++++++++++++++++++++-------- 4 files changed, 56 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 033baca..fcc7e98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -498,7 +498,6 @@ dependencies = [ "serde-wasm-bindgen", "serde_core", "serde_json", - "thiserror", "wasm-bindgen", "wasm-bindgen-test", ] @@ -1022,26 +1021,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "thiserror" -version = "2.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "toml_datetime" version = "0.7.5+spec-1.1.0" diff --git a/Cargo.toml b/Cargo.toml index fe8c273..37c025b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,7 +63,6 @@ logos = { version = "0.16.0", default-features = false, features = [ ] } lalrpop-util = { version = "0.22.2", features = ["lexer"] } itoa = "1.0.16" -thiserror = "2.0.17" hashbrown = "0.16.1" # WASM support (optional) diff --git a/src/error.rs b/src/error.rs index a7e09ce..3a10fdc 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,27 +1,39 @@ use alloc::string::{String, ToString}; -use core::fmt::Display; -use thiserror::Error; +use core::fmt::{Display, Formatter}; pub type Result = core::result::Result; -#[derive(Error, Debug)] +#[derive(Debug)] pub enum Error { - #[error("failed to resolve referenced input `{0}`")] InputResolveError(String), - - #[error("attempted to spread a type that differs from its containing type")] InvalidSpreadError, - - #[error("attempted to interpolate a non-string type into a string")] InvalidInterpolationError, - - #[error("failed to deserialize input: {0}")] DeserializationError(String), - - #[error("failed to parse input: {0}")] ParseError(String), } +impl Display for Error { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + Self::InputResolveError(input) => { + write!(f, "failed to resolve referenced input `{input}`") + } + Self::InvalidSpreadError => write!( + f, + "attempted to spread a type that differs from its containing type" + ), + Self::InvalidInterpolationError => write!( + f, + "attempted to interpolate a non-string type into a string" + ), + Self::DeserializationError(msg) => write!(f, "failed to deserialize input: {msg}"), + Self::ParseError(msg) => write!(f, "failed to parse input: {msg}"), + } + } +} + +impl core::error::Error for Error {} + impl serde_core::de::Error for Error { fn custom(msg: T) -> Self where diff --git a/src/lexer.rs b/src/lexer.rs index 1f83419..a17d853 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -1,7 +1,10 @@ use alloc::{borrow::Cow, string::String, vec::Vec}; -use core::{num::ParseIntError, str::FromStr}; +use core::{ + fmt::{Display, Formatter}, + num::ParseIntError, + str::FromStr, +}; use logos::{Logos, SpannedIter}; -use thiserror::Error; use crate::Integer; @@ -30,17 +33,38 @@ impl<'input> Iterator for Lexer<'input> { } } -#[derive(Debug, Default, Error, Clone, PartialEq, Eq)] +#[derive(Debug, Default, Clone, PartialEq, Eq)] pub enum LexicalError { - #[error("Integer parsing error: {0}")] - InvalidInteger(#[from] ParseIntError), - #[error("Float parsing error: {0}")] - InvalidFloat(#[from] core::num::ParseFloatError), + InvalidInteger(ParseIntError), + InvalidFloat(core::num::ParseFloatError), #[default] - #[error("Encountered invalid token")] InvalidToken, } +impl Display for LexicalError { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + Self::InvalidInteger(err) => write!(f, "Integer parsing error: {err}"), + Self::InvalidFloat(err) => write!(f, "Float parsing error: {err}"), + Self::InvalidToken => write!(f, "Encountered invalid token"), + } + } +} + +impl core::error::Error for LexicalError {} + +impl From for LexicalError { + fn from(err: ParseIntError) -> Self { + Self::InvalidInteger(err) + } +} + +impl From for LexicalError { + fn from(err: core::num::ParseFloatError) -> Self { + Self::InvalidFloat(err) + } +} + #[derive(Logos, Debug, Clone, PartialEq)] #[logos(error = LexicalError)] #[logos(skip r"[\s\t\r\n\f]+")] // Whitespace