diff --git a/Cargo.lock b/Cargo.lock index dd93c797..7cd49507 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,8 +101,8 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if", - "getrandom", + "cfg-if 1.0.0", + "getrandom 0.2.15", "once_cell", "version_check", "zerocopy", @@ -312,7 +312,7 @@ checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ "async-lock 2.8.0", "autocfg", - "cfg-if", + "cfg-if 1.0.0", "concurrent-queue", "futures-lite 1.13.0", "log", @@ -331,7 +331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" dependencies = [ "async-lock 3.4.0", - "cfg-if", + "cfg-if 1.0.0", "concurrent-queue", "futures-io", "futures-lite 2.3.0", @@ -379,7 +379,7 @@ dependencies = [ "async-lock 2.8.0", "async-signal", "blocking", - "cfg-if", + "cfg-if 1.0.0", "event-listener 3.1.0", "futures-lite 1.13.0", "rustix 0.38.34", @@ -406,7 +406,7 @@ dependencies = [ "async-io 2.3.3", "async-lock 3.4.0", "atomic-waker", - "cfg-if", + "cfg-if 1.0.0", "futures-core", "futures-io", "rustix 0.38.34", @@ -528,13 +528,34 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", ] [[package]] @@ -603,6 +624,12 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + [[package]] name = "bytemuck" version = "1.16.0" @@ -629,6 +656,16 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + [[package]] name = "bytes" version = "1.6.0" @@ -687,6 +724,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[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" @@ -859,7 +902,7 @@ version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ - "bytes", + "bytes 1.6.0", "memchr", ] @@ -870,10 +913,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a2dc81369dde6d31456eedbb4fd3d320f0b9713573dfe06e569e2bce7607f2" dependencies = [ "castaway", - "cfg-if", + "cfg-if 1.0.0", "itoa", "rustversion", "ryu", + "serde", "static_assertions", ] @@ -941,7 +985,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -968,12 +1012,12 @@ dependencies = [ "bitflags 2.5.0", "crossterm_winapi", "libc", - "mio", + "mio 0.8.11", "parking_lot", "serde", "signal-hook", "signal-hook-mio", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -982,7 +1026,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -991,7 +1035,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -1023,13 +1067,22 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", + "block-buffer 0.10.4", "crypto-common", ] @@ -1113,7 +1166,7 @@ dependencies = [ "wasm-bindgen-futures", "web-sys", "web-time", - "winapi", + "winapi 0.3.9", "winit", ] @@ -1293,6 +1346,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + [[package]] name = "fastrand" version = "1.9.0" @@ -1314,7 +1373,7 @@ version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "rustix 0.38.34", "windows-sys 0.52.0", ] @@ -1334,7 +1393,7 @@ version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall 0.4.1", "windows-sys 0.52.0", @@ -1407,6 +1466,22 @@ dependencies = [ "libc", ] +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags 1.3.2", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + [[package]] name = "futures-core" version = "0.3.30" @@ -1475,6 +1550,15 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1495,15 +1579,26 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -1622,7 +1717,7 @@ dependencies = [ "log", "presser", "thiserror", - "winapi", + "winapi 0.3.9", "windows 0.52.0", ] @@ -1668,7 +1763,7 @@ dependencies = [ "libloading 0.8.3", "thiserror", "widestring", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1704,6 +1799,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -1917,7 +2018,7 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1941,6 +2042,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.0" @@ -1978,7 +2088,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" dependencies = [ "cesu8", - "cfg-if", + "cfg-if 1.0.0", "combine", "jni-sys", "log", @@ -2011,6 +2121,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "khronos-egl" version = "6.0.0" @@ -2048,6 +2168,12 @@ dependencies = [ "libc", ] +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.155" @@ -2060,8 +2186,8 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ - "cfg-if", - "winapi", + "cfg-if 1.0.0", + "winapi 0.3.9", ] [[package]] @@ -2070,7 +2196,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "windows-targets 0.52.5", ] @@ -2198,6 +2324,25 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + [[package]] name = "mio" version = "0.8.11" @@ -2206,10 +2351,34 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +dependencies = [ + "lazycell", + "log", + "mio 0.6.23", + "slab", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + [[package]] name = "naga" version = "0.19.2" @@ -2261,6 +2430,17 @@ dependencies = [ "jni-sys", ] +[[package]] +name = "net2" +version = "0.2.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + [[package]] name = "nix" version = "0.26.4" @@ -2268,7 +2448,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", - "cfg-if", + "cfg-if 1.0.0", "libc", "memoffset 0.7.1", ] @@ -2280,7 +2460,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.5.0", - "cfg-if", + "cfg-if 1.0.0", "cfg_aliases", "libc", ] @@ -2315,7 +2495,7 @@ dependencies = [ "kqueue", "libc", "log", - "mio", + "mio 0.8.11", "walkdir", "windows-sys 0.48.0", ] @@ -2525,6 +2705,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + [[package]] name = "orbclient" version = "0.3.47" @@ -2585,7 +2771,7 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall 0.5.1", "smallvec", @@ -2664,7 +2850,7 @@ checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ "autocfg", "bitflags 1.3.2", - "cfg-if", + "cfg-if 1.0.0", "concurrent-queue", "libc", "log", @@ -2678,7 +2864,7 @@ version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6a007746f34ed64099e88783b0ae369eaa3da6392868ba262e2af9b8fbaea1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "concurrent-queue", "hermit-abi", "pin-project-lite", @@ -2751,6 +2937,19 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -2758,8 +2957,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -2769,7 +2978,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -2778,7 +2996,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", ] [[package]] @@ -2957,24 +3184,36 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", "syn 2.0.66", ] +[[package]] +name = "serde_json" +version = "1.0.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + [[package]] name = "serde_repr" version = "0.1.19" @@ -2986,15 +3225,27 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug", +] + [[package]] name = "sha1" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", - "digest", + "digest 0.10.7", ] [[package]] @@ -3014,7 +3265,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" dependencies = [ "libc", - "mio", + "mio 0.8.11", "signal-hook", ] @@ -3109,7 +3360,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -3136,8 +3387,11 @@ dependencies = [ "crossterm", "notify", "reedline", + "serde", + "serde_json", "stack-core", "stack-std", + "ws", ] [[package]] @@ -3146,6 +3400,8 @@ version = "0.1.0" dependencies = [ "compact_str", "internment", + "serde", + "serde_json", "test-case", "unicode-segmentation", "yansi", @@ -3258,7 +3514,7 @@ version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fastrand 2.1.0", "rustix 0.38.34", "windows-sys 0.52.0", @@ -3288,7 +3544,7 @@ version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "proc-macro2", "quote", "syn 2.0.66", @@ -3335,7 +3591,7 @@ dependencies = [ "arrayref", "arrayvec", "bytemuck", - "cfg-if", + "cfg-if 1.0.0", "log", "tiny-skia-path", ] @@ -3463,7 +3719,7 @@ checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" dependencies = [ "memoffset 0.9.1", "tempfile", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -3561,6 +3817,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -3573,7 +3835,7 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] @@ -3598,7 +3860,7 @@ version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -3786,7 +4048,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbd7311dbd2abcfebaabf1841a2824ed7c8be443a0f29166e5d3c6a53a762c01" dependencies = [ "arrayvec", - "cfg-if", + "cfg-if 1.0.0", "cfg_aliases", "js-sys", "log", @@ -3867,7 +4129,7 @@ dependencies = [ "wasm-bindgen", "web-sys", "wgpu-types", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -3887,6 +4149,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -3897,6 +4165,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -4265,6 +4539,34 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +[[package]] +name = "ws" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25fe90c75f236a0a00247d5900226aea4f2d7b05ccc34da9e7a8880ff59b5848" +dependencies = [ + "byteorder", + "bytes 0.4.12", + "httparse", + "log", + "mio 0.6.23", + "mio-extras", + "rand 0.7.3", + "sha-1", + "slab", + "url", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "x11-dl" version = "2.21.0" @@ -4395,14 +4697,14 @@ dependencies = [ "nix 0.26.4", "once_cell", "ordered-stream", - "rand", + "rand 0.8.5", "serde", "serde_repr", "sha1", "static_assertions", "tracing", "uds_windows", - "winapi", + "winapi 0.3.9", "xdg-home", "zbus_macros", "zbus_names", diff --git a/Cargo.toml b/Cargo.toml index ab0bfd9f..2591731a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,9 @@ members = ["stack-core", "stack-std", "stack-cli", "stack-debugger"] [workspace.dependencies] unicode-segmentation = "1" -compact_str = "=0.8.0-beta" +compact_str = { version = "=0.8.0-beta", features = ["serde"] } test-case = "3" -clap = { version = "4", features = ["derive"] } \ No newline at end of file +clap = { version = "4", features = ["derive"] } +serde = { version = "1.0.204", features = ["derive"] } +serde_json = "1.0.121" diff --git a/justfile b/justfile index 549b8a02..2cb0f628 100644 --- a/justfile +++ b/justfile @@ -9,3 +9,9 @@ debug file: serve: cd docs; mdbook serve --open + +ws-serve: + cargo run -p stack-cli -- serve + +ws-connect: + rlwrap websocat ws://localhost:5001 diff --git a/stack-cli/Cargo.toml b/stack-cli/Cargo.toml index 9d831234..a41a874a 100644 --- a/stack-cli/Cargo.toml +++ b/stack-cli/Cargo.toml @@ -17,6 +17,11 @@ stack-core = { path = "../stack-core" } stack-std = { path = "../stack-std", optional = true } codespan-reporting = "0.11.1" +# server +serde = { workspace = true } +ws = { version = "0.9.2" } +serde_json.workspace = true + [[bin]] name = "stack" path = "src/main.rs" diff --git a/stack-cli/src/lib.rs b/stack-cli/src/lib.rs new file mode 100644 index 00000000..87721235 --- /dev/null +++ b/stack-cli/src/lib.rs @@ -0,0 +1,58 @@ +use core::fmt; +use std::io::{self, prelude::Write}; + +use crossterm::{ + cursor::{self, MoveTo}, + style::Print, + terminal, QueueableCommand, +}; +use stack_core::prelude::*; + +pub mod server; + +pub fn ok_or_exit<T, E>(result: Result<T, E>) -> T +where + E: fmt::Display, +{ + match result { + Ok(x) => x, + Err(e) => { + eprintln!("error: {e}"); + std::process::exit(1); + } + } +} + +pub fn print_stack(context: &Context) { + print!("stack:"); + + core::iter::repeat(" ") + .zip(context.stack()) + .for_each(|(sep, x)| print!("{sep}{x:#}")); + + println!() +} + +pub fn eprint_stack(context: &Context) { + eprint!("stack:"); + + core::iter::repeat(" ") + .zip(context.stack()) + .for_each(|(sep, x)| eprint!("{sep}{x:#}")); + + eprintln!() +} + +pub fn clear_screen() -> io::Result<()> { + let mut stdout = std::io::stdout(); + + stdout.queue(cursor::Hide)?; + let (_, num_lines) = terminal::size()?; + for _ in 0..2 * num_lines { + stdout.queue(Print("\n"))?; + } + stdout.queue(MoveTo(0, 0))?; + stdout.queue(cursor::Show)?; + + stdout.flush() +} diff --git a/stack-cli/src/main.rs b/stack-cli/src/main.rs index b544dc59..3f90ca8c 100644 --- a/stack-cli/src/main.rs +++ b/stack-cli/src/main.rs @@ -1,6 +1,5 @@ -use core::fmt; use std::{ - io::{self, prelude::Write, Read}, + io::Read, path::{Path, PathBuf}, sync::Arc, }; @@ -14,15 +13,13 @@ use codespan_reporting::{ termcolor::{ColorChoice, StandardStream}, }, }; -use crossterm::{ - cursor::{self, MoveTo}, - style::Print, - terminal, QueueableCommand, -}; use notify::{ Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher, }; use reedline::{DefaultPrompt, DefaultPromptSegment, Reedline, Signal}; +use stack_cli::{ + clear_screen, eprint_stack, ok_or_exit, print_stack, server::listen, +}; use stack_core::prelude::*; fn main() { @@ -223,56 +220,10 @@ fn main() { } } } + Subcommand::Serve => listen(), } } -fn ok_or_exit<T, E>(result: Result<T, E>) -> T -where - E: fmt::Display, -{ - match result { - Ok(x) => x, - Err(e) => { - eprintln!("error: {e}"); - std::process::exit(1); - } - } -} - -fn print_stack(context: &Context) { - print!("stack:"); - - core::iter::repeat(" ") - .zip(context.stack()) - .for_each(|(sep, x)| print!("{sep}{x:#}")); - - println!() -} - -fn eprint_stack(context: &Context) { - eprint!("stack:"); - - core::iter::repeat(" ") - .zip(context.stack()) - .for_each(|(sep, x)| eprint!("{sep}{x:#}")); - - eprintln!() -} - -fn clear_screen() -> io::Result<()> { - let mut stdout = std::io::stdout(); - - stdout.queue(cursor::Hide)?; - let (_, num_lines) = terminal::size()?; - for _ in 0..2 * num_lines { - stdout.queue(Print("\n"))?; - } - stdout.queue(MoveTo(0, 0))?; - stdout.queue(cursor::Show)?; - - stdout.flush() -} - #[derive(Debug, Clone, PartialEq, Eq, Default, clap::Parser)] #[command(author, version, about, long_about = None)] #[command(propagate_version = true)] @@ -329,4 +280,7 @@ enum Subcommand { #[arg(short, long)] watch: bool, }, + + // TODO: add host and port as options + Serve, } diff --git a/stack-cli/src/server.rs b/stack-cli/src/server.rs new file mode 100644 index 00000000..103f6478 --- /dev/null +++ b/stack-cli/src/server.rs @@ -0,0 +1,282 @@ +use stack_core::prelude::*; +use std::{collections::HashMap, mem, rc::Rc, sync::Mutex}; + +use serde::{Deserialize, Serialize}; +use ws::{Message, Sender}; + +use crate::{eprint_stack, print_stack}; + +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum Incoming { + // Execution + Run(RunPayload), + RunNew(RunPayload), + + // Querying + Stack(BasePayload), + Context(BasePayload), +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct RunPayload { + pub id: u32, + pub code: String, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct BasePayload { + pub id: u32, +} + +impl Incoming { + pub fn id(&self) -> u32 { + match self { + Incoming::Run(payload) | Incoming::RunNew(payload) => payload.id, + Incoming::Stack(payload) | Incoming::Context(payload) => payload.id, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "error", rename_all = "snake_case")] +pub enum OutgoingError { + RunError(RunErrorPayload), + ParseError(ParseErrorPayload), + CommandError(CommandErrorPayload), +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RunErrorPayload { + pub for_id: u32, + pub value: RunError, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ParseErrorPayload { + pub for_id: u32, + pub value: ParseError, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CommandErrorPayload { + pub for_id: u32, + pub value: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "status", rename_all = "snake_case")] +pub enum Outgoing { + Ok(OkPayload), + Error(OutgoingError), +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum OkPayload { + Single(SinglePayload), + Null(NullPayload), + Many(ManyPayload), + Map(MapPayload), + Context(ContextPayload), +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SinglePayload { + pub for_id: u32, + pub value: Expr, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct NullPayload { + pub for_id: u32, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ManyPayload { + pub for_id: u32, + pub value: Vec<Expr>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MapPayload { + pub for_id: u32, + pub value: HashMap<String, Expr>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ContextPayload { + pub for_id: u32, + pub value: Context, +} + +impl Outgoing { + pub fn for_id(&self) -> u32 { + match self { + Outgoing::Ok(payload) => match payload { + OkPayload::Single(p) => p.for_id, + OkPayload::Null(p) => p.for_id, + OkPayload::Many(p) => p.for_id, + OkPayload::Map(p) => p.for_id, + OkPayload::Context(p) => p.for_id, + }, + Outgoing::Error(error) => match error { + OutgoingError::RunError(p) => p.for_id, + OutgoingError::ParseError(p) => p.for_id, + OutgoingError::CommandError(p) => p.for_id, + }, + } + } +} + +#[allow(clippy::result_large_err)] +fn run( + code: String, + eng_mutex: Rc<Mutex<Engine>>, + ctx_mutex: Rc<Mutex<Context>>, + out: &Sender, + id: u32, + reset: bool, +) -> ws::Result<()> { + let source = Source::new("runner", code); + let mut lexer = Lexer::new(source); + let exprs = match parse(&mut lexer) { + Ok(e) => e, + Err(err) => { + return out.send( + serde_json::to_string(&Outgoing::Error(OutgoingError::ParseError( + ParseErrorPayload { + for_id: id, + value: err, + }, + ))) + .unwrap(), + ); + } + }; + + match (eng_mutex.try_lock(), ctx_mutex.try_lock()) { + (Ok(engine), Ok(mut guard)) => { + if reset { + let _ = mem::replace(&mut *guard, Context::new()); + } + + let context = mem::take(&mut *guard); + let result = engine.run(context, exprs); + + match result { + Ok(ctx) => { + print_stack(&ctx); + *guard = ctx; + + match guard.stack().last().cloned() { + Some(expr) => out.send( + serde_json::to_string(&Outgoing::Ok(OkPayload::Single( + SinglePayload { + for_id: id, + value: expr, + }, + ))) + .unwrap(), + ), + None => out.send( + serde_json::to_string(&Outgoing::Ok(OkPayload::Null( + NullPayload { for_id: id }, + ))) + .unwrap(), + ), + } + } + Err(e) => { + eprintln!("error: {e}"); + eprint_stack(&e.context); + + out.send( + serde_json::to_string(&Outgoing::Error(OutgoingError::RunError( + RunErrorPayload { + for_id: id, + value: e, + }, + ))) + .unwrap(), + ) + } + } + } + _ => todo!("mutex not lock"), + } +} + +#[allow(clippy::result_large_err)] +pub fn handle( + out: &Sender, + msg: &Message, + eng_mutex: Rc<Mutex<Engine>>, + ctx_mutex: Rc<Mutex<Context>>, +) -> ws::Result<()> { + if let Message::Text(string) = msg { + let request = serde_json::from_str::<Incoming>(string); + + match request { + Ok(incoming) => match incoming { + Incoming::RunNew(RunPayload { id, code }) => { + run(code, eng_mutex, ctx_mutex, out, id, true) + } + Incoming::Run(RunPayload { id, code }) => { + run(code, eng_mutex, ctx_mutex, out, id, false) + } + + Incoming::Stack(BasePayload { id }) => match ctx_mutex.try_lock() { + Ok(context) => out.send( + serde_json::to_string(&Outgoing::Ok(OkPayload::Many( + ManyPayload { + for_id: id, + value: context.stack().to_vec(), + }, + ))) + .unwrap(), + ), + Err(_) => todo!(), + }, + Incoming::Context(BasePayload { id }) => match ctx_mutex.try_lock() { + Ok(context) => out.send( + serde_json::to_string(&Outgoing::Ok(OkPayload::Context( + ContextPayload { + for_id: id, + value: context.clone(), + }, + ))) + .unwrap(), + ), + Err(_) => todo!(), + }, + }, + Err(parse_error) => out.send( + serde_json::to_string(&Outgoing::Error(OutgoingError::CommandError( + CommandErrorPayload { + // TODO: we don't get an ID here so this is a special case + for_id: 0, + value: parse_error.to_string(), + }, + ))) + .unwrap(), + ), + } + } else { + todo!("message not text") + } +} + +pub fn listen() { + let eng_mutex = Rc::new(Mutex::new(Engine::new())); + let ctx_mutex = Rc::new(Mutex::new(Context::new())); + + println!("Websocket server running on ws://localhost:5501"); + ws::listen("localhost:5001", |out| { + let eng_mutex = eng_mutex.clone(); + let ctx_mutex = ctx_mutex.clone(); + + move |msg| handle(&out, &msg, eng_mutex.clone(), ctx_mutex.clone()) + }) + .unwrap(); +} diff --git a/stack-core/Cargo.toml b/stack-core/Cargo.toml index e4a7effb..87f19513 100644 --- a/stack-core/Cargo.toml +++ b/stack-core/Cargo.toml @@ -8,6 +8,8 @@ internment = "0.7.4" unicode-segmentation.workspace = true compact_str.workspace = true yansi = "1" +serde.workspace = true [dev-dependencies] test-case.workspace = true +serde_json.workspace = true diff --git a/stack-core/src/chain.rs b/stack-core/src/chain.rs index f34a390f..1d57a950 100644 --- a/stack-core/src/chain.rs +++ b/stack-core/src/chain.rs @@ -1,10 +1,10 @@ use core::{cell::RefCell, fmt}; -use std::{borrow::BorrowMut, sync::Arc}; +use std::{borrow::BorrowMut, rc::Rc}; #[derive(PartialEq, Clone)] pub struct Chain<T> { - value: Arc<RefCell<T>>, - child: Option<Arc<RefCell<Chain<T>>>>, + value: Rc<RefCell<T>>, + child: Option<Rc<RefCell<Chain<T>>>>, root: bool, } @@ -20,14 +20,14 @@ where impl<T> Chain<T> { pub fn new(value: T) -> Self { Self { - value: Arc::new(RefCell::new(value)), + value: Rc::new(RefCell::new(value)), child: None, root: true, } } - pub fn link(&mut self) -> Arc<RefCell<Self>> { - let child = Arc::new(RefCell::new(Self { + pub fn link(&mut self) -> Rc<RefCell<Self>> { + let child = Rc::new(RefCell::new(Self { value: self.value.clone(), child: None, root: false, @@ -37,7 +37,7 @@ impl<T> Chain<T> { child } - pub fn root(&self) -> Arc<RefCell<T>> { + pub fn root(&self) -> Rc<RefCell<T>> { self.value.clone() } @@ -54,7 +54,7 @@ where self.value.borrow().clone() } - fn unlink_with_rc(&mut self, value: Arc<RefCell<T>>, new_root: bool) { + fn unlink_with_rc(&mut self, value: Rc<RefCell<T>>, new_root: bool) { let mut new_root = new_root; if new_root { @@ -70,7 +70,7 @@ where } pub fn unlink_with(&mut self, val: T) { - self.unlink_with_rc(Arc::new(RefCell::new(val)), true); + self.unlink_with_rc(Rc::new(RefCell::new(val)), true); } pub fn set(&mut self, val: T) { diff --git a/stack-core/src/context.rs b/stack-core/src/context.rs index 13434577..a1318521 100644 --- a/stack-core/src/context.rs +++ b/stack-core/src/context.rs @@ -1,4 +1,6 @@ -use std::{cell::RefCell, collections::HashMap, sync::Arc}; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; + +use serde::{Deserialize, Serialize}; use crate::{ chain::Chain, @@ -12,7 +14,7 @@ use crate::{ }; // TODO: This API could be a lot nicer. -#[derive(Debug, Clone, PartialEq, Default)] +#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct Context { stack: Vec<Expr>, scopes: VecOne<Scope>, @@ -162,7 +164,7 @@ impl Context { #[inline] pub fn scope_items( &self, - ) -> impl Iterator<Item = (&Symbol, &Arc<RefCell<Chain<Option<Expr>>>>)> { + ) -> impl Iterator<Item = (&Symbol, &Rc<RefCell<Chain<Option<Expr>>>>)> { self.scopes.last().items.iter() } @@ -239,3 +241,23 @@ impl Context { self.scopes.try_pop(); } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_ser_and_de() { + let mut context = Context::new(); + context.stack_push(ExprKind::Integer(2).into()).unwrap(); + context.def_scope_item( + Symbol::from_ref("foo"), + ExprKind::Symbol(Symbol::from_ref("bar")).into(), + ); + + let json = serde_json::to_string(&context).unwrap(); + let ser_context: Context = serde_json::from_str(json.as_str()).unwrap(); + + assert_eq!(context, ser_context); + } +} diff --git a/stack-core/src/engine.rs b/stack-core/src/engine.rs index 8c0382a5..384424d7 100644 --- a/stack-core/src/engine.rs +++ b/stack-core/src/engine.rs @@ -5,6 +5,8 @@ use std::{ time::{Duration, Instant}, }; +use serde::{Deserialize, Serialize}; + use crate::{ context::Context, expr::{Expr, ExprKind, FnScope}, @@ -350,7 +352,7 @@ impl Engine { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct RunError { pub reason: RunErrorReason, pub context: Context, @@ -371,7 +373,7 @@ impl fmt::Display for RunError { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum RunErrorReason { StackUnderflow, DoubleError, @@ -613,4 +615,20 @@ mod tests { vec![&ExprKind::Integer(1), &ExprKind::Integer(2),] ); } + + #[test] + fn test_ser_and_de() { + let source = Source::new("", "0 'a def 2 2 + '(fn)"); + let mut lexer = Lexer::new(source); + let exprs = crate::parser::parse(&mut lexer).unwrap(); + + let engine = Engine::new(); + let mut context = Context::new().with_stack_capacity(32); + context = engine.run(context, exprs).unwrap(); + + let json = serde_json::to_string(&context).unwrap(); + let ser_context: Context = serde_json::from_str(json.as_str()).unwrap(); + + assert_eq!(context, ser_context); + } } diff --git a/stack-core/src/expr.rs b/stack-core/src/expr.rs index 989f303d..b8636470 100644 --- a/stack-core/src/expr.rs +++ b/stack-core/src/expr.rs @@ -3,11 +3,12 @@ use std::collections::HashMap; use compact_str::CompactString; use internment::Intern; -use yansi::Paint; +use serde::Deserialize; +use serde::Serialize; use crate::{lexer::Span, scope::Scope, source::Source, symbol::Symbol}; -#[derive(Clone)] +#[derive(Clone, Serialize, Deserialize)] pub struct Expr { pub kind: ExprKind, pub info: Option<ExprInfo>, @@ -98,7 +99,7 @@ pub fn display_fn_scope(scope: &FnScope) -> String { .into() } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum FnScope { Scoped(Scope), Scopeless, @@ -116,7 +117,7 @@ impl FnScope { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum ExprKind { Nil, @@ -216,6 +217,17 @@ impl PartialEq for ExprKind { (Self::List(lhs), Self::List(rhs)) => lhs == rhs, (Self::Record(lhs), Self::Record(rhs)) => lhs == rhs, + ( + Self::Function { + scope: lhs_scope, + body: lhs_body, + }, + Self::Function { + scope: rhs_scope, + body: rhs_body, + }, + ) => lhs_scope == rhs_scope && lhs_body == rhs_body, + ( Self::SExpr { call: lhs_call, @@ -337,6 +349,8 @@ impl ops::Rem for ExprKind { impl fmt::Display for ExprKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use yansi::Paint; + // TODO: Is there a nicer way to do this that avoids the duplication? if f.alternate() { match self { @@ -511,7 +525,7 @@ impl fmt::Display for ErrorInner { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct ExprInfo { pub source: Source, pub span: Span, diff --git a/stack-core/src/journal.rs b/stack-core/src/journal.rs index deb372a0..dff6ea7a 100644 --- a/stack-core/src/journal.rs +++ b/stack-core/src/journal.rs @@ -1,13 +1,15 @@ use core::fmt; use std::collections::HashMap; +use serde::{Deserialize, Serialize}; + use crate::{ expr::{Expr, ExprInfo, ExprKind}, scope::Scope, symbol::Symbol, }; -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct JournalEntry { pub ops: Vec<JournalOp>, pub scope_level: usize, @@ -39,7 +41,7 @@ impl JournalEntry { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum JournalOp { Call(Expr), SCall(Expr), @@ -123,7 +125,7 @@ impl From<Scope> for JournalScope { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] // TODO: implement this as a ring buffer with max_commits so we never go over pub struct Journal { ops: Vec<JournalOp>, diff --git a/stack-core/src/lexer.rs b/stack-core/src/lexer.rs index 56e9f563..6256abaf 100644 --- a/stack-core/src/lexer.rs +++ b/stack-core/src/lexer.rs @@ -1,8 +1,10 @@ use core::{fmt, ops::Range}; +use serde::{Deserialize, Serialize}; + use crate::source::Source; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub struct Token { pub kind: TokenKind, pub span: Span, @@ -14,7 +16,7 @@ impl fmt::Display for Token { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Span { /// The lower byte bound (inclusive). pub start: usize, @@ -33,7 +35,7 @@ impl Span { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum TokenKind { Invalid, Eof, diff --git a/stack-core/src/parser.rs b/stack-core/src/parser.rs index bf241099..dd669e4f 100644 --- a/stack-core/src/parser.rs +++ b/stack-core/src/parser.rs @@ -1,5 +1,6 @@ use compact_str::ToCompactString; use core::fmt; +use serde::{Deserialize, Serialize}; use std::collections::HashMap; use crate::{ @@ -256,7 +257,7 @@ fn parse_record( } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct ParseError { pub source: Source, pub kind: ParseErrorKind, @@ -280,7 +281,7 @@ impl fmt::Display for ParseError { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub enum ParseErrorKind { UnexpectedToken(Token), InvalidLiteral(Token), diff --git a/stack-core/src/scope.rs b/stack-core/src/scope.rs index 11b7cc23..0f1c4b01 100644 --- a/stack-core/src/scope.rs +++ b/stack-core/src/scope.rs @@ -1,15 +1,101 @@ use core::fmt; -use std::{cell::RefCell, collections::HashMap, fmt::Formatter, sync::Arc}; +use std::{cell::RefCell, collections::HashMap, fmt::Formatter, rc::Rc}; + +use serde::{ + ser::{Serialize, SerializeMap}, + Deserialize, Deserializer, +}; use crate::{chain::Chain, expr::FnScope, prelude::*}; -pub type Val = Arc<RefCell<Chain<Option<Expr>>>>; +pub type Val = Rc<RefCell<Chain<Option<Expr>>>>; -#[derive(Default, PartialEq)] +#[derive(Default)] pub struct Scope { pub items: HashMap<Symbol, Val>, } +impl PartialEq for Scope { + fn eq(&self, other: &Self) -> bool { + let a: HashMap<Symbol, Expr> = HashMap::from_iter( + self + .items + .iter() + .map(|(k, v)| (*k, v.borrow().val().clone().unwrap())), + ); + + let b: HashMap<Symbol, Expr> = HashMap::from_iter( + other + .items + .iter() + .map(|(k, v)| (*k, v.borrow().val().clone().unwrap())), + ); + + a == b + } +} + +impl Serialize for Scope { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + let mut map = serializer.serialize_map(Some(self.items.len()))?; + for (k, v) in self.items.iter() { + // TODO: don't unwrap and handle the error somehow + let expr: Expr = v.borrow().val().unwrap(); + map.serialize_entry(k, &expr)?; + } + map.end() + } +} + +impl<'de> Deserialize<'de> for Scope { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + // Helper struct to deserialize the items + #[derive(Deserialize)] + #[serde(transparent)] + struct ScopeHelper { + items: HashMap<String, DeserializeVal>, + } + + // Helper enum to deserialize Val + #[derive(Deserialize)] + #[serde(untagged)] + enum DeserializeVal { + Some(Expr), + None, + } + + // Deserialize into the helper struct + let helper = ScopeHelper::deserialize(deserializer)?; + + // Convert DeserializeVal to Val + let mut items: HashMap<String, Val> = helper + .items + .into_iter() + .map(|(k, v)| { + let val = match v { + DeserializeVal::Some(expr) => { + Rc::new(RefCell::new(Chain::new(Some(expr)))) + } + DeserializeVal::None => Rc::new(RefCell::new(Chain::new(None))), + }; + (k, val) + }) + .collect(); + let mut scope: HashMap<Symbol, Val> = HashMap::new(); + for (k, v) in items.drain() { + scope.insert(Symbol::from_ref(k.as_str()), v); + } + + Ok(Scope { items: scope }) + } +} + impl fmt::Debug for Scope { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let iter = self.items.iter().map(|(name, item)| (name.as_str(), item)); @@ -18,7 +104,7 @@ impl fmt::Debug for Scope { } impl Clone for Scope { - /// Clones the scope, using the same Arc's as self + /// Clones the scope, using the same Rc's as self fn clone(&self) -> Self { let mut items = HashMap::new(); @@ -53,7 +139,7 @@ impl Scope { c.clone() } else { - let val = Arc::new(RefCell::new(Chain::new(Some(item)))); + let val = Rc::new(RefCell::new(Chain::new(Some(item)))); self.items.insert(name, val.clone()); val @@ -64,7 +150,7 @@ impl Scope { self .items .entry(name) - .or_insert_with(|| Arc::new(RefCell::new(Chain::new(None)))); + .or_insert_with(|| Rc::new(RefCell::new(Chain::new(None)))); } pub fn set( diff --git a/stack-core/src/source.rs b/stack-core/src/source.rs index 5e96f3b8..0b1eae4e 100644 --- a/stack-core/src/source.rs +++ b/stack-core/src/source.rs @@ -3,6 +3,7 @@ use core::{fmt, num::NonZeroUsize}; use std::{fs, io, path::Path, sync::Arc}; +use serde::{Deserialize, Deserializer, Serialize}; use unicode_segmentation::UnicodeSegmentation; /// Contains metadata for a source. @@ -11,6 +12,28 @@ use unicode_segmentation::UnicodeSegmentation; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Source(Arc<SourceInner>); +impl Serialize for Source { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + self.0.serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for Source { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + // First, deserialize SourceInner + let inner = SourceInner::deserialize(deserializer)?; + + // Then wrap it in an Arc and return Source + Ok(Source(Arc::new(inner))) + } +} + impl Source { /// Creates a new [`Source`]. pub fn new<N, S>(name: N, source: S) -> Self @@ -126,7 +149,8 @@ impl fmt::Display for Location { } } -#[derive(Debug, Clone, Eq)] +#[derive(Debug, Clone, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] struct SourceInner { name: String, source: String, diff --git a/stack-core/src/symbol.rs b/stack-core/src/symbol.rs index 56b66fe2..0db01b92 100644 --- a/stack-core/src/symbol.rs +++ b/stack-core/src/symbol.rs @@ -2,6 +2,10 @@ use core::{borrow::Borrow, fmt, hash::Hash}; use compact_str::{CompactString, ToCompactString}; use internment::Intern; +use serde::{ + de::{self, Visitor}, + Deserialize, Deserializer, Serialize, +}; use crate::expr::ExprKind; @@ -9,6 +13,53 @@ use crate::expr::ExprKind; #[repr(transparent)] pub struct Symbol(Intern<CompactString>); +impl Serialize for Symbol { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + // TODO: is this okay to make Symbol transparently a string? + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> Deserialize<'de> for Symbol { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + struct SymbolVisitor; + + impl<'de> Visitor<'de> for SymbolVisitor { + type Value = Symbol; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string") + } + + fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> + where + E: de::Error, + { + // Convert the &str to CompactString and intern it + let compact_string = CompactString::new(value); + Ok(Symbol(Intern::new(compact_string))) + } + + fn visit_string<E>(self, value: String) -> Result<Self::Value, E> + where + E: de::Error, + { + // Convert the String to CompactString and intern it + let compact_string = CompactString::new(value); + Ok(Symbol(Intern::new(compact_string))) + } + } + + deserializer.deserialize_str(SymbolVisitor) + } +} + impl Symbol { /// Creates a [`Symbol`]. #[inline] diff --git a/stack-core/src/vec_one.rs b/stack-core/src/vec_one.rs index 3d55cc48..f72717b5 100644 --- a/stack-core/src/vec_one.rs +++ b/stack-core/src/vec_one.rs @@ -3,8 +3,21 @@ use core::slice::{Iter, IterMut, SliceIndex}; use std::vec::IntoIter; +use serde::{Deserialize, Serialize}; + /// A [`Vec`] with at least one element. -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Default, + Serialize, + Deserialize, +)] pub(crate) struct VecOne<T> { vec: Vec<T>, }