Compare commits

...

37 Commits

Author SHA1 Message Date
Tony Garnock-Jones b10acaf4a6 Builder image for workflows
/ build (push) Successful in 4m37s Details
2024-05-31 15:00:18 +02:00
Tony Garnock-Jones b9053ad881 Workflow for building syndicate-server in CI
/ build (push) Has been cancelled Details
2024-05-31 14:57:59 +02:00
Tony Garnock-Jones 8311b0a020 Initial workflow
/ build (push) Successful in 1m12s Details
2024-05-31 10:10:02 +02:00
Tony Garnock-Jones 64a4074273 rustup-and-install.sh 2024-05-28 09:37:50 +02:00
Tony Garnock-Jones 53d859e50f Bump deps 2024-05-28 09:37:46 +02:00
Tony Garnock-Jones d301c09b02 Release independent packages
syndicate@0.40.1

Generated by cargo-workspaces
2024-05-24 09:32:28 +02:00
Tony Garnock-Jones 2bff59c41a Bump deps 2024-05-24 09:30:42 +02:00
Tony Garnock-Jones 39f0e8cdf1 Handle Packet::Nop 2024-05-19 21:54:48 +02:00
Tony Garnock-Jones 3e0d6af497 Merge latest changes from the syndicate-protocols repository 2024-05-19 21:51:31 +02:00
Tony Garnock-Jones 599b4ed469 Packet::Nop 2024-05-19 21:32:44 +02:00
Tony Garnock-Jones 6e555c9fd5 Update binary schemas 2024-04-19 12:57:14 +02:00
Emery Hemingway 8ebde104ca http: order absent fields first
This makes the absent variants the default initialization for
some implementations.
2024-04-19 10:51:40 +02:00
Tony Garnock-Jones 6468e16790 Bump preserves dep 2024-04-12 19:57:23 +02:00
Tony Garnock-Jones 65101e900e Release independent packages
syndicate@0.40.0
syndicate-macros@0.32.0
syndicate-schema-plugin@0.9.0
syndicate-server@0.45.0
syndicate-tools@0.18.0

Generated by cargo-workspaces
2024-04-10 17:04:25 +02:00
Tony Garnock-Jones 581886835a New dataspace pattern implementation; update HTTP server 2024-04-10 17:03:09 +02:00
Tony Garnock-Jones dcb1aec142 Merge latest changes from the syndicate-protocols repository 2024-04-10 15:43:06 +02:00
Tony Garnock-Jones c0239cf322 And with that we are almost back where we started with http.prs! 2024-04-10 15:16:35 +02:00
Tony Garnock-Jones 9cc4175f24 Cope with HTTP/1.0's optional Host header 2024-04-10 14:54:19 +02:00
Tony Garnock-Jones 70f42dd931 Another revision of http.prs 2024-04-10 14:31:27 +02:00
Tony Garnock-Jones ef1ebe6412 Sigh. <done> turns out to be a good idea in addition to <processing> 2024-04-10 13:24:25 +02:00
Tony Garnock-Jones deec008c66 No taskset on osx 2024-04-10 11:07:22 +02:00
Tony Garnock-Jones 008671d0b2 Bump deps incl preserves-schema for a keyword-avoiding fix 2024-04-09 22:41:58 +02:00
Tony Garnock-Jones 9fcf22e1b5 Merge latest changes from the syndicate-protocols repository 2024-04-09 15:16:46 +02:00
Tony Garnock-Jones ca18ca08df Alternative representation of dataspacePatterns 2024-04-09 09:15:21 +02:00
Tony Garnock-Jones 40ca168eac Repair typo 2024-04-09 09:13:51 +02:00
Tony Garnock-Jones 5a73e8d4c3 Alter dataspacePatterns language to make rec and arr more like dict 2024-04-04 16:31:09 +02:00
Tony Garnock-Jones 91b26001d8 There isn't an /etc/mime.types on OSX 2024-04-03 22:32:54 +02:00
Tony Garnock-Jones b83b39515d Release independent packages
syndicate@0.39.0
syndicate-macros@0.31.0
syndicate-schema-plugin@0.8.0
syndicate-server@0.44.0
syndicate-tools@0.17.0

Generated by cargo-workspaces
2024-04-01 16:53:42 +02:00
Tony Garnock-Jones d9fa6362af Merge latest changes from the syndicate-protocols repository 2024-04-01 16:52:57 +02:00
Tony Garnock-Jones 94598a574b Update HTTP service protocol 2024-04-01 16:52:24 +02:00
Tony Garnock-Jones 80ad0914ed Revise http protocol 2024-04-01 16:52:24 +02:00
Tony Garnock-Jones bdb0cc1023 Repair severe error in turn rollback 2024-04-01 16:52:24 +02:00
Tony Garnock-Jones 710ff91a64 Revise http protocol 2024-04-01 15:56:07 +02:00
Tony Garnock-Jones d3748a286b Release independent packages
syndicate-server@0.43.1

Generated by cargo-workspaces
2024-04-01 15:08:11 +02:00
Tony Garnock-Jones a56aec2c30 Tweak tracing in http_router 2024-04-01 15:01:33 +02:00
Tony Garnock-Jones 0c06ae9601 Repair path matching where no explicit PathPatternElement::Rest is present 2024-04-01 14:58:55 +02:00
Tony Garnock-Jones 1f0c9d2883 Dep bump 2024-03-30 11:36:42 +01:00
30 changed files with 726 additions and 538 deletions

View File

@ -0,0 +1,24 @@
on:
push:
branches:
- main
jobs:
build:
runs-on: docker
container:
image: git.syndicate-lang.org/syndicate-lang/rust-builder:latest
steps:
- uses: actions/checkout@v3
- run: CROSS_CONTAINER_IN_CONTAINER=true make ci-release
- uses: actions/upload-artifact@v3
with:
name: syndicate-server-x86_64
path: target/dist/x86_64
- uses: actions/upload-artifact@v3
with:
name: syndicate-server-aarch64
path: target/dist/aarch64
- uses: actions/upload-artifact@v3
with:
name: syndicate-server-armv7
path: target/dist/armv7

View File

@ -0,0 +1,7 @@
FROM rust:latest
RUN cargo install cross
# This is necessary for cross to be able to access /var/run/docker.sock
COPY --from=docker:dind /usr/local/bin/docker /usr/local/bin/
RUN curl -fsSL https://deb.nodesource.com/setup_20.x -o nodesource_setup.sh && bash nodesource_setup.sh && rm -f nodesource_setup.sh && apt -y install nodejs && apt clean

View File

@ -0,0 +1,11 @@
#!/bin/sh
#
# You need to have already logged in:
#
# docker login git.syndicate-lang.org
#
# Use a token with read-only access to user scope, this seems to be sufficient (!)
set -e
docker build -t git.syndicate-lang.org/syndicate-lang/rust-builder .
docker push git.syndicate-lang.org/syndicate-lang/rust-builder

331
Cargo.lock generated
View File

@ -87,47 +87,48 @@ dependencies = [
[[package]] [[package]]
name = "anstream" name = "anstream"
version = "0.6.13" version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"anstyle-parse", "anstyle-parse",
"anstyle-query", "anstyle-query",
"anstyle-wincon", "anstyle-wincon",
"colorchoice", "colorchoice",
"is_terminal_polyfill",
"utf8parse", "utf8parse",
] ]
[[package]] [[package]]
name = "anstyle" name = "anstyle"
version = "1.0.6" version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
[[package]] [[package]]
name = "anstyle-parse" name = "anstyle-parse"
version = "0.2.3" version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
dependencies = [ dependencies = [
"utf8parse", "utf8parse",
] ]
[[package]] [[package]]
name = "anstyle-query" name = "anstyle-query"
version = "1.0.2" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
dependencies = [ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
name = "anstyle-wincon" name = "anstyle-wincon"
version = "3.0.2" version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"windows-sys 0.52.0", "windows-sys 0.52.0",
@ -152,9 +153,9 @@ dependencies = [
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.2.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]] [[package]]
name = "backtrace" name = "backtrace"
@ -209,9 +210,9 @@ dependencies = [
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.15.4" version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@ -233,9 +234,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.90" version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -276,16 +277,16 @@ dependencies = [
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.37" version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [ dependencies = [
"android-tzdata", "android-tzdata",
"iana-time-zone", "iana-time-zone",
"js-sys", "js-sys",
"num-traits", "num-traits",
"wasm-bindgen", "wasm-bindgen",
"windows-targets 0.52.4", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
@ -331,14 +332,14 @@ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
"clap_lex", "clap_lex",
"strsim 0.11.0", "strsim 0.11.1",
] ]
[[package]] [[package]]
name = "clap_complete" name = "clap_complete"
version = "4.5.1" version = "4.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "885e4d7d5af40bfb99ae6f9433e292feac98d452dcb3ec3d25dfe7552b77da8c" checksum = "dd79504325bf38b10165b02e89b4347300f855f273c4cb30c4a3209e6583275e"
dependencies = [ dependencies = [
"clap 4.5.4", "clap 4.5.4",
] ]
@ -352,7 +353,7 @@ dependencies = [
"heck 0.5.0", "heck 0.5.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.55", "syn 2.0.66",
] ]
[[package]] [[package]]
@ -363,9 +364,9 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]] [[package]]
name = "colorchoice" name = "colorchoice"
version = "1.0.0" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]] [[package]]
name = "convert_case" name = "convert_case"
@ -445,9 +446,9 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.19" version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]] [[package]]
name = "crypto-common" name = "crypto-common"
@ -504,9 +505,9 @@ dependencies = [
[[package]] [[package]]
name = "data-encoding" name = "data-encoding"
version = "2.5.0" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
[[package]] [[package]]
name = "digest" name = "digest"
@ -536,9 +537,9 @@ checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
[[package]] [[package]]
name = "either" name = "either"
version = "1.10.0" version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
[[package]] [[package]]
name = "filetime" name = "filetime"
@ -673,7 +674,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.55", "syn 2.0.66",
] ]
[[package]] [[package]]
@ -729,9 +730,9 @@ dependencies = [
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.12" version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"libc", "libc",
@ -929,9 +930,9 @@ dependencies = [
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.12" version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
] ]
@ -945,6 +946,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.5" version = "0.10.5"
@ -993,15 +1000,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.153" version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.11" version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"scopeguard", "scopeguard",
@ -1030,9 +1037,9 @@ checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.7.2" version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
dependencies = [ dependencies = [
"adler", "adler",
] ]
@ -1120,7 +1127,7 @@ dependencies = [
"aes-gcm", "aes-gcm",
"blake2", "blake2",
"chacha20poly1305", "chacha20poly1305",
"getrandom 0.2.12", "getrandom 0.2.15",
"noise-protocol", "noise-protocol",
"sha2", "sha2",
"x25519-dalek", "x25519-dalek",
@ -1147,9 +1154,9 @@ dependencies = [
[[package]] [[package]]
name = "num" name = "num"
version = "0.4.1" version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
dependencies = [ dependencies = [
"num-bigint", "num-bigint",
"num-complex", "num-complex",
@ -1161,20 +1168,19 @@ dependencies = [
[[package]] [[package]]
name = "num-bigint" name = "num-bigint"
version = "0.4.4" version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7"
dependencies = [ dependencies = [
"autocfg",
"num-integer", "num-integer",
"num-traits", "num-traits",
] ]
[[package]] [[package]]
name = "num-complex" name = "num-complex"
version = "0.4.5" version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
dependencies = [ dependencies = [
"num-traits", "num-traits",
] ]
@ -1190,9 +1196,9 @@ dependencies = [
[[package]] [[package]]
name = "num-iter" name = "num-iter"
version = "0.1.44" version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"num-integer", "num-integer",
@ -1201,11 +1207,10 @@ dependencies = [
[[package]] [[package]]
name = "num-rational" name = "num-rational"
version = "0.4.1" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
dependencies = [ dependencies = [
"autocfg",
"num-bigint", "num-bigint",
"num-integer", "num-integer",
"num-traits", "num-traits",
@ -1213,9 +1218,9 @@ dependencies = [
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.18" version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
@ -1280,23 +1285,23 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.55", "syn 2.0.66",
] ]
[[package]] [[package]]
name = "openssl-src" name = "openssl-src"
version = "300.2.3+3.2.1" version = "300.3.0+3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cff92b6f71555b61bb9315f7c64da3ca43d87531622120fea0195fc761b4843" checksum = "eba8804a1c5765b18c4b3f907e6897ebabeedebc9830e1a0046c4a4cf44663e1"
dependencies = [ dependencies = [
"cc", "cc",
] ]
[[package]] [[package]]
name = "openssl-sys" name = "openssl-sys"
version = "0.9.101" version = "0.9.102"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",
@ -1318,12 +1323,12 @@ dependencies = [
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.12.1" version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [ dependencies = [
"lock_api", "lock_api",
"parking_lot_core 0.9.9", "parking_lot_core 0.9.10",
] ]
[[package]] [[package]]
@ -1342,15 +1347,15 @@ dependencies = [
[[package]] [[package]]
name = "parking_lot_core" name = "parking_lot_core"
version = "0.9.9" version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"libc", "libc",
"redox_syscall 0.4.1", "redox_syscall 0.5.1",
"smallvec", "smallvec",
"windows-targets 0.48.5", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
@ -1376,14 +1381,14 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.55", "syn 2.0.66",
] ]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.13" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]] [[package]]
name = "pin-utils" name = "pin-utils"
@ -1399,9 +1404,9 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]] [[package]]
name = "plotters" name = "plotters"
version = "0.3.5" version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3"
dependencies = [ dependencies = [
"num-traits", "num-traits",
"plotters-backend", "plotters-backend",
@ -1412,15 +1417,15 @@ dependencies = [
[[package]] [[package]]
name = "plotters-backend" name = "plotters-backend"
version = "0.3.5" version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7"
[[package]] [[package]]
name = "plotters-svg" name = "plotters-svg"
version = "0.3.5" version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705"
dependencies = [ dependencies = [
"plotters-backend", "plotters-backend",
] ]
@ -1456,9 +1461,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]] [[package]]
name = "preserves" name = "preserves"
version = "4.995.1" version = "4.995.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c160ffeeae615caf059a15ce7ee98dc0aafb6512530263ce35527622867aee04" checksum = "61e3e6deb0d6974f8f8f744fbd9dbfcf70763d7cbd827b8214d7dc22a2beaff1"
dependencies = [ dependencies = [
"base64", "base64",
"dtoa", "dtoa",
@ -1471,9 +1476,9 @@ dependencies = [
[[package]] [[package]]
name = "preserves-schema" name = "preserves-schema"
version = "5.995.0" version = "5.995.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b554f32fe5e2a829cf48d9c41a7e4ef1d6d021e13afd2daf44b8fce052514aa0" checksum = "56e7f701ce176a21b37abf14c3fcd461106c362e1a090150e29bec7768104679"
dependencies = [ dependencies = [
"convert_case", "convert_case",
"glob", "glob",
@ -1510,18 +1515,18 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.79" version = "1.0.84"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.35" version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -1562,7 +1567,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [ dependencies = [
"getrandom 0.2.12", "getrandom 0.2.15",
] ]
[[package]] [[package]]
@ -1603,6 +1608,15 @@ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
] ]
[[package]]
name = "redox_syscall"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
dependencies = [
"bitflags 2.5.0",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.10.4" version = "1.10.4"
@ -1649,15 +1663,15 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.23" version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.17" version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]] [[package]]
name = "same-file" name = "same-file"
@ -1676,9 +1690,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.197" version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
@ -1704,20 +1718,20 @@ dependencies = [
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.197" version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.55", "syn 2.0.66",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.115" version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -1757,9 +1771,9 @@ dependencies = [
[[package]] [[package]]
name = "signal-hook-registry" name = "signal-hook-registry"
version = "1.4.1" version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@ -1781,9 +1795,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.5.6" version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.52.0", "windows-sys 0.52.0",
@ -1797,9 +1811,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.11.0" version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "structopt" name = "structopt"
@ -1844,9 +1858,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.55" version = "2.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1855,13 +1869,13 @@ dependencies = [
[[package]] [[package]]
name = "syndicate" name = "syndicate"
version = "0.38.0" version = "0.40.1"
dependencies = [ dependencies = [
"blake2", "blake2",
"bytes", "bytes",
"criterion", "criterion",
"futures", "futures",
"getrandom 0.2.12", "getrandom 0.2.15",
"hmac", "hmac",
"lazy_static", "lazy_static",
"openssl", "openssl",
@ -1877,7 +1891,7 @@ dependencies = [
[[package]] [[package]]
name = "syndicate-macros" name = "syndicate-macros"
version = "0.30.0" version = "0.32.0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1889,7 +1903,7 @@ dependencies = [
[[package]] [[package]]
name = "syndicate-schema-plugin" name = "syndicate-schema-plugin"
version = "0.7.0" version = "0.9.0"
dependencies = [ dependencies = [
"preserves-schema", "preserves-schema",
"syndicate", "syndicate",
@ -1897,7 +1911,7 @@ dependencies = [
[[package]] [[package]]
name = "syndicate-server" name = "syndicate-server"
version = "0.43.0" version = "0.45.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"futures", "futures",
@ -1907,7 +1921,7 @@ dependencies = [
"noise-protocol", "noise-protocol",
"noise-rust-crypto", "noise-rust-crypto",
"notify", "notify",
"parking_lot 0.12.1", "parking_lot 0.12.3",
"preserves-schema", "preserves-schema",
"structopt", "structopt",
"syndicate", "syndicate",
@ -1924,7 +1938,7 @@ dependencies = [
[[package]] [[package]]
name = "syndicate-tools" name = "syndicate-tools"
version = "0.16.0" version = "0.18.0"
dependencies = [ dependencies = [
"clap 4.5.4", "clap 4.5.4",
"clap_complete", "clap_complete",
@ -1945,22 +1959,22 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.58" version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.58" version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.55", "syn 2.0.66",
] ]
[[package]] [[package]]
@ -2020,9 +2034,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.36.0" version = "1.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes", "bytes",
@ -2044,7 +2058,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.55", "syn 2.0.66",
] ]
[[package]] [[package]]
@ -2109,7 +2123,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.55", "syn 2.0.66",
] ]
[[package]] [[package]]
@ -2235,9 +2249,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.1.11" version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6"
[[package]] [[package]]
name = "universal-hash" name = "universal-hash"
@ -2348,7 +2362,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.55", "syn 2.0.66",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -2370,7 +2384,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.55", "syn 2.0.66",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -2421,11 +2435,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]] [[package]]
name = "winapi-util" name = "winapi-util"
version = "0.1.6" version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
dependencies = [ dependencies = [
"winapi 0.3.9", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -2440,7 +2454,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [ dependencies = [
"windows-targets 0.52.4", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
@ -2458,7 +2472,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [ dependencies = [
"windows-targets 0.52.4", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
@ -2478,17 +2492,18 @@ dependencies = [
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm 0.52.4", "windows_aarch64_gnullvm 0.52.5",
"windows_aarch64_msvc 0.52.4", "windows_aarch64_msvc 0.52.5",
"windows_i686_gnu 0.52.4", "windows_i686_gnu 0.52.5",
"windows_i686_msvc 0.52.4", "windows_i686_gnullvm",
"windows_x86_64_gnu 0.52.4", "windows_i686_msvc 0.52.5",
"windows_x86_64_gnullvm 0.52.4", "windows_x86_64_gnu 0.52.5",
"windows_x86_64_msvc 0.52.4", "windows_x86_64_gnullvm 0.52.5",
"windows_x86_64_msvc 0.52.5",
] ]
[[package]] [[package]]
@ -2499,9 +2514,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
@ -2511,9 +2526,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
@ -2523,9 +2538,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
@ -2535,9 +2556,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
@ -2547,9 +2568,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
@ -2559,9 +2580,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
@ -2571,9 +2592,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]] [[package]]
name = "ws2_32-sys" name = "ws2_32-sys"
@ -2613,5 +2634,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.55", "syn 2.0.66",
] ]

View File

@ -78,3 +78,11 @@ aarch64-binary-release:
aarch64-binary-debug: aarch64-binary-debug:
CARGO_TARGET_DIR=target/target.aarch64 cross build --target=aarch64-unknown-linux-musl --all-targets --features vendored-openssl CARGO_TARGET_DIR=target/target.aarch64 cross build --target=aarch64-unknown-linux-musl --all-targets --features vendored-openssl
ci-release: x86_64-binary-release aarch64-binary-release armv7-binary-release
rm -rf target/dist
for arch in x86_64 aarch64 armv7; do \
mkdir -p target/dist/$$arch; \
cp -a target/target.$$arch/$$arch-unknown-linux-musl*/release/syndicate-macaroon target/dist/$$arch; \
cp -a target/target.$$arch/$$arch-unknown-linux-musl*/release/syndicate-server target/dist/$$arch; \
done

View File

@ -1,2 +1,7 @@
#!/bin/sh #!/bin/sh
make -C ../syndicate-server binary && exec taskset -c 0,1 ../target/release/syndicate-server -c benchmark-config.pr "$@" TASKSET='taskset -c 0,1'
if [ $(uname -s) = 'Darwin' ]
then
TASKSET=
fi
make -C ../syndicate-server binary && exec $TASKSET ../target/release/syndicate-server -c benchmark-config.pr "$@"

4
rustup-and-install.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
set -e
rustup update
cargo +nightly install --path `pwd`/syndicate-server

View File

@ -1,6 +1,6 @@
[package] [package]
name = "syndicate-macros" name = "syndicate-macros"
version = "0.30.0" version = "0.32.0"
authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"] authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"]
edition = "2018" edition = "2018"
@ -13,7 +13,7 @@ license = "Apache-2.0"
proc-macro = true proc-macro = true
[dependencies] [dependencies]
syndicate = { path = "../syndicate", version = "0.38.0"} syndicate = { path = "../syndicate", version = "0.40.0"}
proc-macro2 = { version = "^1.0", features = ["span-locations"] } proc-macro2 = { version = "^1.0", features = ["span-locations"] }
quote = "^1.0" quote = "^1.0"

View File

@ -36,7 +36,7 @@ enum SymbolVariant<'a> {
fn compile_sequence_members(vs: &[IOValue]) -> Vec<TokenStream> { fn compile_sequence_members(vs: &[IOValue]) -> Vec<TokenStream> {
vs.iter().enumerate().map(|(i, f)| { vs.iter().enumerate().map(|(i, f)| {
let p = compile_pattern(f); let p = compile_pattern(f);
quote!((#i .into(), #p)) quote!((syndicate::value::Value::from(#i).wrap(), #p))
}).collect::<Vec<_>>() }).collect::<Vec<_>>()
} }
@ -151,16 +151,14 @@ fn compile_pattern(v: &IOValue) -> TokenStream {
#[allow(non_snake_case)] #[allow(non_snake_case)]
let V_: TokenStream = quote!(syndicate::value); let V_: TokenStream = quote!(syndicate::value);
#[allow(non_snake_case)] #[allow(non_snake_case)]
let MapFromIterator_: TokenStream = quote!(<#V_::Map<_, _> as std::iter::FromIterator<_>>::from_iter); let MapFrom_: TokenStream = quote!(<#V_::Map<_, _>>::from);
match v.value() { match v.value() {
Value::Symbol(s) => match analyze_symbol(&s, true) { Value::Symbol(s) => match analyze_symbol(&s, true) {
SymbolVariant::Binder(_) => SymbolVariant::Binder(_) =>
quote!(#P_::Pattern::DBind(Box::new(#P_::DBind { quote!(#P_::Pattern::Bind{ pattern: Box::new(#P_::Pattern::Discard) }),
pattern: #P_::Pattern::DDiscard(Box::new(#P_::DDiscard))
}))),
SymbolVariant::Discard => SymbolVariant::Discard =>
quote!(#P_::Pattern::DDiscard(Box::new(#P_::DDiscard))), quote!(#P_::Pattern::Discard),
SymbolVariant::Substitution(s) => SymbolVariant::Substitution(s) =>
lit(Ident::new(s, Span::call_site())), lit(Ident::new(s, Span::call_site())),
SymbolVariant::Normal(_) => SymbolVariant::Normal(_) =>
@ -172,9 +170,7 @@ fn compile_pattern(v: &IOValue) -> TokenStream {
Some(label) => Some(label) =>
if label.starts_with("$") && r.arity() == 1 { if label.starts_with("$") && r.arity() == 1 {
let nested = compile_pattern(&r.fields()[0]); let nested = compile_pattern(&r.fields()[0]);
quote!(#P_::Pattern::DBind(Box::new(#P_::DBind { quote!(#P_::Pattern::Bind{ pattern: Box::new(#nested) })
pattern: #nested
})))
} else { } else {
let label_stx = if label.starts_with("=") { let label_stx = if label.starts_with("=") {
let id = Ident::new(&label[1..], Span::call_site()); let id = Ident::new(&label[1..], Span::call_site());
@ -183,18 +179,19 @@ fn compile_pattern(v: &IOValue) -> TokenStream {
quote!(#V_::Value::symbol(#label).wrap()) quote!(#V_::Value::symbol(#label).wrap())
}; };
let members = compile_sequence_members(r.fields()); let members = compile_sequence_members(r.fields());
quote!(#P_::Pattern::DCompound(Box::new(#P_::DCompound::Rec { quote!(#P_::Pattern::Group {
label: #label_stx, type_: Box::new(#P_::GroupType::Rec { label: #label_stx }),
fields: vec![#(#members),*], entries: #MapFrom_([#(#members),*]),
}))) })
} }
} }
} }
Value::Sequence(vs) => { Value::Sequence(vs) => {
let members = compile_sequence_members(vs); let members = compile_sequence_members(vs);
quote!(#P_::Pattern::DCompound(Box::new(#P_::DCompound::Arr { quote!(#P_::Pattern::Group {
items: vec![#(#members),*], type_: Box::new(#P_::GroupType::Arr),
}))) entries: #MapFrom_([#(#members),*]),
})
} }
Value::Set(_) => Value::Set(_) =>
panic!("Cannot match sets in patterns"), panic!("Cannot match sets in patterns"),
@ -204,9 +201,10 @@ fn compile_pattern(v: &IOValue) -> TokenStream {
let v = compile_pattern(v); let v = compile_pattern(v);
quote!((#k, #v)) quote!((#k, #v))
}).collect::<Vec<_>>(); }).collect::<Vec<_>>();
quote!(#P_::Pattern::DCompound(Box::new(#P_::DCompound::Dict { quote!(#P_::Pattern::Group {
entries: #MapFromIterator_(vec![#(#members),*]) type_: Box::new(#P_::GroupType::Dict),
}))) entries: #MapFrom_([#(#members),*]),
})
} }
_ => lit(ValueCompiler::for_patterns().compile(v)), _ => lit(ValueCompiler::for_patterns().compile(v)),
} }

View File

@ -15,10 +15,9 @@ pub fn lit<T: ToTokens>(e: T) -> TokenStream2 {
} }
fn compile_sequence_members(stxs: &Vec<Stx>) -> Result<Vec<TokenStream2>, &'static str> { fn compile_sequence_members(stxs: &Vec<Stx>) -> Result<Vec<TokenStream2>, &'static str> {
stxs.iter().map(|stx| { stxs.iter().enumerate().map(|(i, stx)| {
// let p = to_pattern_expr(stx)?; let p = to_pattern_expr(stx)?;
// Ok(quote!(#p)) Ok(quote!((syndicate::value::Value::from(#i).wrap(), #p)))
to_pattern_expr(stx)
}).collect() }).collect()
} }
@ -28,7 +27,7 @@ pub fn to_pattern_expr(stx: &Stx) -> Result<TokenStream2, &'static str> {
#[allow(non_snake_case)] #[allow(non_snake_case)]
let V_: TokenStream2 = quote!(syndicate::value); let V_: TokenStream2 = quote!(syndicate::value);
#[allow(non_snake_case)] #[allow(non_snake_case)]
let MapFromIterator_: TokenStream2 = quote!(<#V_::Map<_, _> as std::iter::FromIterator<_>>::from_iter); let MapFrom_: TokenStream2 = quote!(<#V_::Map<_, _>>::from);
match stx { match stx {
Stx::Atom(v) => Stx::Atom(v) =>
@ -41,26 +40,27 @@ pub fn to_pattern_expr(stx: &Stx) -> Result<TokenStream2, &'static str> {
None => to_pattern_expr(&Stx::Discard)?, None => to_pattern_expr(&Stx::Discard)?,
} }
}; };
Ok(quote!(#P_::Pattern::DBind(Box::new(#P_::DBind { pattern: #inner_pat_expr })))) Ok(quote!(#P_::Pattern::Bind { pattern: Box::new(#inner_pat_expr) }))
} }
Stx::Subst(e) => Stx::Subst(e) =>
Ok(lit(e)), Ok(lit(e)),
Stx::Discard => Stx::Discard =>
Ok(quote!(#P_::Pattern::DDiscard(Box::new(#P_::DDiscard)))), Ok(quote!(#P_::Pattern::Discard)),
Stx::Rec(l, fs) => { Stx::Rec(l, fs) => {
let label = to_value_expr(&*l)?; let label = to_value_expr(&*l)?;
let members = compile_sequence_members(fs)?; let members = compile_sequence_members(fs)?;
Ok(quote!(#P_::Pattern::DCompound(Box::new(#P_::DCompound::Rec { Ok(quote!(#P_::Pattern::Group {
label: #label, type_: Box::new(#P_::GroupType::Rec { label: #label }),
fields: vec![#(#members),*], entries: #MapFrom_([#(#members),*]),
})))) }))
}, },
Stx::Seq(stxs) => { Stx::Seq(stxs) => {
let members = compile_sequence_members(stxs)?; let members = compile_sequence_members(stxs)?;
Ok(quote!(#P_::Pattern::DCompound(Box::new(#P_::DCompound::Arr { Ok(quote!(#P_::Pattern::Group {
items: vec![#(#members),*], type_: Box::new(#P_::GroupType::Arr),
})))) entries: #MapFrom_([#(#members),*]),
}))
} }
Stx::Set(_stxs) => Stx::Set(_stxs) =>
Err("Set literals not supported in patterns"), Err("Set literals not supported in patterns"),
@ -70,9 +70,10 @@ pub fn to_pattern_expr(stx: &Stx) -> Result<TokenStream2, &'static str> {
let v = to_pattern_expr(v)?; let v = to_pattern_expr(v)?;
Ok(quote!((#k, #v))) Ok(quote!((#k, #v)))
}).collect::<Result<Vec<_>, &'static str>>()?; }).collect::<Result<Vec<_>, &'static str>>()?;
Ok(quote!(#P_::Pattern::DCompound(Box::new(#P_::DCompound::Dict { Ok(quote!(#P_::Pattern::Group {
entries: #MapFromIterator_(vec![#(#members),*]) type_: Box::new(#P_::GroupType::Dict),
})))) entries: #MapFrom_([#(#members),*])
}))
} }
} }
} }

View File

@ -0,0 +1,15 @@
{
"folders": [
{
"path": "."
},
{
"path": "../syndicate-protocols"
}
],
"settings": {
"files.exclude": {
"target": true
}
}
}

View File

@ -1,6 +1,6 @@
[package] [package]
name = "syndicate-schema-plugin" name = "syndicate-schema-plugin"
version = "0.7.0" version = "0.9.0"
authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"] authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"]
edition = "2018" edition = "2018"
@ -13,7 +13,7 @@ license = "Apache-2.0"
[dependencies] [dependencies]
preserves-schema = "5.995" preserves-schema = "5.995"
syndicate = { path = "../syndicate", version = "0.38.0"} syndicate = { path = "../syndicate", version = "0.40.0"}
[package.metadata.workspaces] [package.metadata.workspaces]
independent = true independent = true

View File

@ -61,7 +61,7 @@ impl Plugin for PatternPlugin {
} }
fn discard() -> P::Pattern { fn discard() -> P::Pattern {
P::Pattern::DDiscard(Box::new(P::DDiscard)) P::Pattern::Discard
} }
trait WildcardPattern { trait WildcardPattern {
@ -94,33 +94,34 @@ fn from_io(v: &IOValue) -> Option<P::_Any> {
impl WildcardPattern for CompoundPattern { impl WildcardPattern for CompoundPattern {
fn wc(&self, s: &mut WalkState) -> Option<P::Pattern> { fn wc(&self, s: &mut WalkState) -> Option<P::Pattern> {
match self { match self {
CompoundPattern::Tuple { patterns } => CompoundPattern::Tuple { patterns } |
Some(P::Pattern::DCompound(Box::new(P::DCompound::Arr { CompoundPattern::TuplePrefix { fixed: patterns, .. }=>
items: patterns.iter() Some(P::Pattern::Group {
.map(|p| unname(p).wc(s)) type_: Box::new(P::GroupType::Arr),
.collect::<Option<Vec<P::Pattern>>>()?, entries: patterns.iter().enumerate()
}))), .map(|(i, p)| Some((P::_Any::new(i), unname(p).wc(s)?)))
CompoundPattern::TuplePrefix { .. } => .collect::<Option<Map<P::_Any, P::Pattern>>>()?,
Some(discard()), }),
CompoundPattern::Dict { entries } => CompoundPattern::Dict { entries } =>
Some(P::Pattern::DCompound(Box::new(P::DCompound::Dict { Some(P::Pattern::Group {
type_: Box::new(P::GroupType::Dict),
entries: Map::from_iter( entries: Map::from_iter(
entries.0.iter() entries.0.iter()
.map(|(k, p)| Some((from_io(k)?, unname_simple(p).wc(s)?))) .map(|(k, p)| Some((from_io(k)?, unname_simple(p).wc(s)?)))
.filter(|e| discard() != e.as_ref().unwrap().1) .filter(|e| discard() != e.as_ref().unwrap().1)
.collect::<Option<Vec<(P::_Any, P::Pattern)>>>()? .collect::<Option<Vec<(P::_Any, P::Pattern)>>>()?
.into_iter()), .into_iter()),
}))), }),
CompoundPattern::Rec { label, fields } => match (unname(label), unname(fields)) { CompoundPattern::Rec { label, fields } => match (unname(label), unname(fields)) {
(Pattern::SimplePattern(label), Pattern::CompoundPattern(fields)) => (Pattern::SimplePattern(label), Pattern::CompoundPattern(fields)) =>
match (*label, *fields) { match (*label, *fields) {
(SimplePattern::Lit { value }, CompoundPattern::Tuple { patterns }) => (SimplePattern::Lit { value }, CompoundPattern::Tuple { patterns }) =>
Some(P::Pattern::DCompound(Box::new(P::DCompound::Rec { Some(P::Pattern::Group{
label: from_io(&value)?, type_: Box::new(P::GroupType::Rec { label: from_io(&value)? }),
fields: patterns.iter() entries: patterns.iter().enumerate()
.map(|p| unname(p).wc(s)) .map(|(i, p)| Some((P::_Any::new(i), unname(p).wc(s)?)))
.collect::<Option<Vec<P::Pattern>>>()?, .collect::<Option<Map<P::_Any, P::Pattern>>>()?,
}))), }),
_ => None, _ => None,
}, },
_ => None, _ => None,

View File

@ -1,6 +1,6 @@
[package] [package]
name = "syndicate-server" name = "syndicate-server"
version = "0.43.0" version = "0.45.0"
authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"] authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"]
edition = "2018" edition = "2018"
@ -14,13 +14,13 @@ jemalloc = ["dep:tikv-jemallocator"]
[build-dependencies] [build-dependencies]
preserves-schema = "5.995" preserves-schema = "5.995"
syndicate = { path = "../syndicate", version = "0.38.0"} syndicate = { path = "../syndicate", version = "0.40.0"}
syndicate-schema-plugin = { path = "../syndicate-schema-plugin", version = "0.7.0"} syndicate-schema-plugin = { path = "../syndicate-schema-plugin", version = "0.9.0"}
[dependencies] [dependencies]
preserves-schema = "5.995" preserves-schema = "5.995"
syndicate = { path = "../syndicate", version = "0.38.0"} syndicate = { path = "../syndicate", version = "0.40.0"}
syndicate-macros = { path = "../syndicate-macros", version = "0.30.0"} syndicate-macros = { path = "../syndicate-macros", version = "0.32.0"}
chrono = "0.4" chrono = "0.4"
futures = "0.3" futures = "0.3"

View File

@ -32,13 +32,9 @@ pub fn empty_response(code: StatusCode) -> Response<Body> {
type ChunkItem = Result<body::Bytes, Box<dyn std::error::Error + Send + Sync>>; type ChunkItem = Result<body::Bytes, Box<dyn std::error::Error + Send + Sync>>;
enum ResponseCollector { struct ResponseCollector {
Pending { tx_res: Option<(oneshot::Sender<Response<Body>>, Response<Body>)>,
tx: oneshot::Sender<Response<Body>>, body_tx: Option<UnboundedSender<ChunkItem>>,
body_tx: UnboundedSender<ChunkItem>,
res: Response<Body>,
},
Done
} }
impl ResponseCollector { impl ResponseCollector {
@ -46,43 +42,50 @@ impl ResponseCollector {
let (body_tx, body_rx) = unbounded_channel(); let (body_tx, body_rx) = unbounded_channel();
let body_stream: Box<dyn futures::Stream<Item = ChunkItem> + Send> = let body_stream: Box<dyn futures::Stream<Item = ChunkItem> + Send> =
Box::new(UnboundedReceiverStream::new(body_rx)); Box::new(UnboundedReceiverStream::new(body_rx));
ResponseCollector::Pending { let mut res = Response::new(body_stream.into());
tx, *res.status_mut() = StatusCode::OK;
body_tx, ResponseCollector {
res: Response::new(body_stream.into()), tx_res: Some((tx, res)),
body_tx: Some(body_tx),
} }
} }
fn with_res<F: FnOnce(&mut Response<Body>) -> ActorResult>(&mut self, f: F) -> ActorResult { fn with_res<F: FnOnce(&mut Response<Body>) -> ActorResult>(&mut self, f: F) -> ActorResult {
if let ResponseCollector::Pending { res, .. } = self { if let Some((_, res)) = &mut self.tx_res {
f(res)?; f(res)?;
} }
Ok(()) Ok(())
} }
fn deliver_res(&mut self) {
if let Some((tx, res)) = std::mem::replace(&mut self.tx_res, None) {
let _ = tx.send(res);
}
}
fn add_chunk(&mut self, value: http::Chunk) -> ActorResult { fn add_chunk(&mut self, value: http::Chunk) -> ActorResult {
if let ResponseCollector::Pending { body_tx, .. } = self { self.deliver_res();
if let Some(body_tx) = self.body_tx.as_mut() {
body_tx.send(Ok(match value { body_tx.send(Ok(match value {
http::Chunk::Bytes(bs) => bs.into(), http::Chunk::Bytes(bs) => bs.into(),
http::Chunk::String(s) => s.as_bytes().to_vec().into(), http::Chunk::String(s) => s.as_bytes().to_vec().into(),
}))?; }))?;
} }
Ok(()) Ok(())
} }
fn finish(&mut self) -> ActorResult { fn finish(&mut self, t: &mut Activation) -> ActorResult {
match std::mem::replace(self, ResponseCollector::Done) { self.deliver_res();
ResponseCollector::Pending { tx, res, .. } => { self.body_tx = None;
let _ = tx.send(res); t.stop();
}
ResponseCollector::Done => (),
}
Ok(()) Ok(())
} }
} }
impl Entity<http::HttpResponse> for ResponseCollector { impl Entity<http::HttpResponse> for ResponseCollector {
fn message(&mut self, _turn: &mut Activation, message: http::HttpResponse) -> ActorResult { fn message(&mut self, t: &mut Activation, message: http::HttpResponse) -> ActorResult {
match message { match message {
http::HttpResponse::Status { code, .. } => self.with_res(|r| { http::HttpResponse::Status { code, .. } => self.with_res(|r| {
*r.status_mut() = StatusCode::from_u16( *r.status_mut() = StatusCode::from_u16(
@ -94,10 +97,12 @@ impl Entity<http::HttpResponse> for ResponseCollector {
HeaderValue::from_str(value.as_str())?); HeaderValue::from_str(value.as_str())?);
Ok(()) Ok(())
}), }),
http::HttpResponse::Chunk { chunk } => self.add_chunk(*chunk), http::HttpResponse::Chunk { chunk } => {
self.add_chunk(*chunk)
}
http::HttpResponse::Done { chunk } => { http::HttpResponse::Done { chunk } => {
self.add_chunk(*chunk)?; self.add_chunk(*chunk)?;
self.finish() self.finish(t)
} }
} }
} }
@ -111,11 +116,11 @@ pub async fn serve(
port: u16, port: u16,
) -> Result<Response<Body>, Error> { ) -> Result<Response<Body>, Error> {
let host = match req.headers().get("host").and_then(|v| v.to_str().ok()) { let host = match req.headers().get("host").and_then(|v| v.to_str().ok()) {
None => return Ok(empty_response(StatusCode::BAD_REQUEST)), None => http::RequestHost::Absent,
Some(h) => match h.rsplit_once(':') { Some(h) => http::RequestHost::Present(match h.rsplit_once(':') {
None => h.to_string(), None => h.to_string(),
Some((h, _port)) => h.to_string(), Some((h, _port)) => h.to_string(),
} })
}; };
let uri = req.uri(); let uri = req.uri();
@ -160,34 +165,29 @@ pub async fn serve(
let account = Account::new(Some(AnyValue::symbol("http")), trace_collector); let account = Account::new(Some(AnyValue::symbol("http")), trace_collector);
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
let mut req_handle: Option<Handle> = None;
facet.activate(&account, Some(trace::TurnCause::external("http")), |t| { facet.activate(&account, Some(trace::TurnCause::external("http")), |t| {
let sreq = http::HttpRequest { t.facet(move |t| {
sequence_number: NEXT_SEQ.fetch_add(1, Ordering::Relaxed).into(), let sreq = http::HttpRequest {
host, sequence_number: NEXT_SEQ.fetch_add(1, Ordering::Relaxed).into(),
port: port.into(), host,
method: req.method().to_string().to_lowercase(), port: port.into(),
path, method: req.method().to_string().to_lowercase(),
headers: http::Headers(headers), path,
query, headers: http::Headers(headers),
body, query,
}; body,
tracing::debug!(?sreq); };
let srep = Cap::guard(&language().syndicate, t.create(ResponseCollector::new(tx))); tracing::debug!(?sreq);
req_handle = httpd.assert(t, language(), &http::HttpContext { req: sreq, res: srep }); let srep = Cap::guard(&language().syndicate, t.create(ResponseCollector::new(tx)));
httpd.assert(t, language(), &http::HttpContext { req: sreq, res: srep });
Ok(())
})?;
Ok(()) Ok(())
}); });
let response_result = rx.await; let response_result = rx.await;
facet.activate(&account, Some(trace::TurnCause::external("http")), |t| {
if let Some(h) = req_handle {
t.retract(h);
}
Ok(())
});
match response_result { match response_result {
Ok(response) => Ok(response), Ok(response) => Ok(response),
Err(_ /* sender dropped */) => Ok(empty_response(StatusCode::INTERNAL_SERVER_ERROR)), Err(_ /* sender dropped */) => Ok(empty_response(StatusCode::INTERNAL_SERVER_ERROR)),

View File

@ -9,7 +9,7 @@ use syndicate::actor::*;
use syndicate::dataspace::Dataspace; use syndicate::dataspace::Dataspace;
use syndicate::during; use syndicate::during;
use syndicate::enclose; use syndicate::enclose;
use syndicate::pattern::{lift_literal, drop_literal}; use syndicate::pattern::{lift_literal, drop_literal, pattern_seq_from_dictionary};
use syndicate::schemas::dataspace; use syndicate::schemas::dataspace;
use syndicate::schemas::dataspace_patterns as P; use syndicate::schemas::dataspace_patterns as P;
use syndicate::schemas::sturdy; use syndicate::schemas::sturdy;
@ -173,7 +173,7 @@ fn bad_instruction(message: &str) -> io::Error {
} }
fn discard() -> P::Pattern { fn discard() -> P::Pattern {
P::Pattern::DDiscard(Box::new(P::DDiscard)) P::Pattern::Discard
} }
fn dlit(value: AnyValue) -> P::Pattern { fn dlit(value: AnyValue) -> P::Pattern {
@ -272,7 +272,7 @@ impl<'env> PatternInstantiator<'env> {
Symbolic::Discard => discard(), Symbolic::Discard => discard(),
Symbolic::Binder(s) => { Symbolic::Binder(s) => {
self.binding_names.push(s); self.binding_names.push(s);
P::Pattern::DBind(Box::new(P::DBind { pattern: discard() })) P::Pattern::Bind { pattern: Box::new(discard()) }
} }
Symbolic::Reference(s) => Symbolic::Reference(s) =>
dlit(self.env.lookup(&s, "pattern-template variable")?.clone()), dlit(self.env.lookup(&s, "pattern-template variable")?.clone()),
@ -287,43 +287,47 @@ impl<'env> PatternInstantiator<'env> {
Some(pat) => pat, Some(pat) => pat,
None => { None => {
let label = self.instantiate_pattern(r.label())?; let label = self.instantiate_pattern(r.label())?;
let fields = r.fields().iter().map(|p| self.instantiate_pattern(p)) let entries = r.fields().iter().enumerate()
.collect::<io::Result<Vec<P::Pattern>>>()?; .map(|(i, p)| Ok((AnyValue::new(i), self.instantiate_pattern(p)?)))
P::Pattern::DCompound(Box::new(P::DCompound::Rec { .collect::<io::Result<Map<AnyValue, P::Pattern>>>()?;
label: drop_literal(&label) P::Pattern::Group {
.ok_or(bad_instruction("Record pattern must have literal label"))?, type_: Box::new(P::GroupType::Rec {
fields, label: drop_literal(&label)
})) .ok_or(bad_instruction("Record pattern must have literal label"))?,
}),
entries,
}
} }
} }
}, },
Value::Sequence(v) => Value::Sequence(v) =>
P::Pattern::DCompound(Box::new(P::DCompound::Arr { P::Pattern::Group {
items: v.iter() type_: Box::new(P::GroupType::Arr),
.map(|p| self.instantiate_pattern(p)) entries: v.iter().enumerate()
.collect::<io::Result<Vec<P::Pattern>>>()?, .map(|(i, p)| Ok((AnyValue::new(i), self.instantiate_pattern(p)?)))
})), .collect::<io::Result<Map<AnyValue, P::Pattern>>>()?,
},
Value::Set(_) => Value::Set(_) =>
Err(bad_instruction(&format!("Sets not permitted in patterns: {:?}", template)))?, Err(bad_instruction(&format!("Sets not permitted in patterns: {:?}", template)))?,
Value::Dictionary(v) => Value::Dictionary(v) =>
P::Pattern::DCompound(Box::new(P::DCompound::Dict { P::Pattern::Group {
type_: Box::new(P::GroupType::Dict),
entries: v.iter() entries: v.iter()
.map(|(a, b)| Ok((a.clone(), self.instantiate_pattern(b)?))) .map(|(a, b)| Ok((a.clone(), self.instantiate_pattern(b)?)))
.collect::<io::Result<Map<AnyValue, P::Pattern>>>()?, .collect::<io::Result<Map<AnyValue, P::Pattern>>>()?,
})), },
}) })
} }
fn maybe_binder_with_pattern(&mut self, r: &Record<AnyValue>) -> io::Result<Option<P::Pattern>> { fn maybe_binder_with_pattern(&mut self, r: &Record<AnyValue>) -> io::Result<Option<P::Pattern>> {
match r.label().value().as_symbol().map(|s| analyze(&s)) { match r.label().value().as_symbol().map(|s| analyze(&s)) {
Some(Symbolic::Binder(formal)) => if r.fields().len() == 1 { Some(Symbolic::Binder(formal)) if r.fields().len() == 1 => {
let pattern = self.instantiate_pattern(&r.fields()[0])?; let pattern = self.instantiate_pattern(&r.fields()[0])?;
self.binding_names.push(formal); self.binding_names.push(formal);
return Ok(Some(P::Pattern::DBind(Box::new(P::DBind { pattern })))); Ok(Some(P::Pattern::Bind { pattern: Box::new(pattern) }))
}, },
_ => (), _ => Ok(None),
} }
Ok(None)
} }
} }
@ -553,7 +557,7 @@ impl Env {
RewriteTemplate::Accept { pattern_template } => { RewriteTemplate::Accept { pattern_template } => {
let (_binding_names, pattern) = self.instantiate_pattern(pattern_template)?; let (_binding_names, pattern) = self.instantiate_pattern(pattern_template)?;
Ok(sturdy::Rewrite { Ok(sturdy::Rewrite {
pattern: embed_pattern(&P::Pattern::DBind(Box::new(P::DBind { pattern }))), pattern: embed_pattern(&P::Pattern::Bind { pattern: Box::new(pattern) }),
template: sturdy::Template::TRef(Box::new(sturdy::TRef { binding: 0.into() })), template: sturdy::Template::TRef(Box::new(sturdy::TRef { binding: 0.into() })),
}) })
} }
@ -674,24 +678,26 @@ impl Env {
fn embed_pattern(p: &P::Pattern) -> sturdy::Pattern { fn embed_pattern(p: &P::Pattern) -> sturdy::Pattern {
match p { match p {
P::Pattern::DDiscard(_) => sturdy::Pattern::PDiscard(Box::new(sturdy::PDiscard)), P::Pattern::Discard => sturdy::Pattern::PDiscard(Box::new(sturdy::PDiscard)),
P::Pattern::DBind(b) => sturdy::Pattern::PBind(Box::new(sturdy::PBind { P::Pattern::Bind { pattern } => sturdy::Pattern::PBind(Box::new(sturdy::PBind {
pattern: embed_pattern(&b.pattern), pattern: embed_pattern(&**pattern),
})), })),
P::Pattern::DLit(b) => sturdy::Pattern::Lit(Box::new(sturdy::Lit { P::Pattern::Lit { value } => sturdy::Pattern::Lit(Box::new(sturdy::Lit {
value: language().unparse(&b.value), value: language().unparse(&**value),
})), })),
P::Pattern::DCompound(b) => sturdy::Pattern::PCompound(Box::new(match &**b { P::Pattern::Group { type_, entries } => sturdy::Pattern::PCompound(Box::new(match &**type_ {
P::DCompound::Rec { label, fields } => P::GroupType::Rec { label } =>
sturdy::PCompound::Rec { sturdy::PCompound::Rec {
label: label.clone(), label: label.clone(),
fields: fields.iter().map(embed_pattern).collect(), fields: pattern_seq_from_dictionary(entries).expect("correct field entries")
.into_iter().map(embed_pattern).collect(),
}, },
P::DCompound::Arr { items } => P::GroupType::Arr =>
sturdy::PCompound::Arr { sturdy::PCompound::Arr {
items: items.iter().map(embed_pattern).collect(), items: pattern_seq_from_dictionary(entries).expect("correct element entries")
.into_iter().map(embed_pattern).collect(),
}, },
P::DCompound::Dict { entries } => P::GroupType::Dict =>
sturdy::PCompound::Dict { sturdy::PCompound::Dict {
entries: entries.iter().map(|(k, v)| (k.clone(), embed_pattern(v))).collect(), entries: entries.iter().map(|(k, v)| (k.clone(), embed_pattern(v))).collect(),
}, },

View File

@ -10,7 +10,6 @@ use syndicate::error::Error;
use syndicate::preserves::rec; use syndicate::preserves::rec;
use syndicate::preserves::value::Map; use syndicate::preserves::value::Map;
use syndicate::preserves::value::NestedValue; use syndicate::preserves::value::NestedValue;
use syndicate::preserves::value::Set;
use syndicate::schemas::http; use syndicate::schemas::http;
use syndicate::value::signed_integer::SignedInteger; use syndicate::value::signed_integer::SignedInteger;
@ -22,7 +21,7 @@ use crate::schemas::internal_services::HttpStaticFileServer;
use syndicate_macros::during; use syndicate_macros::during;
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref MIME_TABLE: Map<String, String> = load_mime_table("/etc/mime.types").expect("MIME table"); pub static ref MIME_TABLE: Map<String, String> = load_mime_table("/etc/mime.types").unwrap_or_default();
} }
pub fn load_mime_table(path: &str) -> Result<Map<String, String>, std::io::Error> { pub fn load_mime_table(path: &str) -> Result<Map<String, String>, std::io::Error> {
@ -56,10 +55,22 @@ pub fn on_demand(t: &mut Activation, ds: Arc<Cap>) {
}); });
} }
type MethodTable = Map<http::MethodPattern, Set<Arc<Cap>>>; #[derive(Debug, Clone)]
struct ActiveHandler {
cap: Arc<Cap>,
terminated: Arc<Field<bool>>,
}
type MethodTable = Map<http::MethodPattern, Vec<ActiveHandler>>;
type HostTable = Map<http::HostPattern, Map<http::PathPattern, MethodTable>>; type HostTable = Map<http::HostPattern, Map<http::PathPattern, MethodTable>>;
type RoutingTable = Map<SignedInteger, HostTable>; type RoutingTable = Map<SignedInteger, HostTable>;
fn request_host(value: &http::RequestHost) -> Option<String> {
match value {
http::RequestHost::Present(h) => Some(h.to_owned()),
http::RequestHost::Absent => None,
}
}
fn run(t: &mut Activation, ds: Arc<Cap>, spec: HttpRouter) -> ActorResult { fn run(t: &mut Activation, ds: Arc<Cap>, spec: HttpRouter) -> ActorResult {
ds.assert(t, language(), &lifecycle::started(&spec)); ds.assert(t, language(), &lifecycle::started(&spec));
ds.assert(t, language(), &lifecycle::ready(&spec)); ds.assert(t, language(), &lifecycle::ready(&spec));
@ -72,25 +83,35 @@ fn run(t: &mut Activation, ds: Arc<Cap>, spec: HttpRouter) -> ActorResult {
enclose!((httpd, routes) during!(t, httpd, language(), <http-listener #(&port1)>, enclose!((routes, port) |t: &mut Activation| { enclose!((httpd, routes) during!(t, httpd, language(), <http-listener #(&port1)>, enclose!((routes, port) |t: &mut Activation| {
let port2 = port.clone(); let port2 = port.clone();
during!(t, httpd, language(), <http-bind $host #(&port2) $method $path $handler>, |t: &mut Activation| { during!(t, httpd, language(), <http-bind $host #(&port2) $method $path $handler>, |t: &mut Activation| {
tracing::debug!("+HTTP binding {:?} {:?} {:?} {:?} {:?}", host, port, method, path, handler);
let port = port.value().to_signedinteger()?; let port = port.value().to_signedinteger()?;
let host = language().parse::<http::HostPattern>(&host)?; let host = language().parse::<http::HostPattern>(&host)?;
let path = language().parse::<http::PathPattern>(&path)?; let path = language().parse::<http::PathPattern>(&path)?;
let method = language().parse::<http::MethodPattern>(&method)?; let method = language().parse::<http::MethodPattern>(&method)?;
let handler = handler.value().to_embedded()?; let handler_cap = handler.value().to_embedded()?.clone();
let handler_terminated = t.named_field("handler-terminated", false);
t.get_mut(&routes) t.get_mut(&routes)
.entry(port.clone()).or_default() .entry(port.clone()).or_default()
.entry(host.clone()).or_default() .entry(host.clone()).or_default()
.entry(path.clone()).or_default() .entry(path.clone()).or_default()
.entry(method.clone()).or_default() .entry(method.clone()).or_default()
.insert(handler.clone()); .push(ActiveHandler {
t.on_stop(enclose!((routes, handler, method, path, host, port) move |t| { cap: handler_cap.clone(),
terminated: handler_terminated,
});
t.on_stop(enclose!((routes, method, path, host, port) move |t| {
tracing::debug!("-HTTP binding {:?} {:?} {:?} {:?} {:?}", host, port, method, path, handler);
let port_map = t.get_mut(&routes); let port_map = t.get_mut(&routes);
let host_map = port_map.entry(port.clone()).or_default(); let host_map = port_map.entry(port.clone()).or_default();
let path_map = host_map.entry(host.clone()).or_default(); let path_map = host_map.entry(host.clone()).or_default();
let method_map = path_map.entry(path.clone()).or_default(); let method_map = path_map.entry(path.clone()).or_default();
let handler_set = method_map.entry(method.clone()).or_default(); let handler_vec = method_map.entry(method.clone()).or_default();
handler_set.remove(&handler); let handler = {
if handler_set.is_empty() { let i = handler_vec.iter().position(|a| a.cap == handler_cap)
.expect("Expected an index of an active handler to remove");
handler_vec.swap_remove(i)
};
if handler_vec.is_empty() {
method_map.remove(&method); method_map.remove(&method);
} }
if method_map.is_empty() { if method_map.is_empty() {
@ -102,6 +123,7 @@ fn run(t: &mut Activation, ds: Arc<Cap>, spec: HttpRouter) -> ActorResult {
if host_map.is_empty() { if host_map.is_empty() {
port_map.remove(&port); port_map.remove(&port);
} }
*t.get_mut(&handler.terminated) = true;
Ok(()) Ok(())
})); }));
Ok(()) Ok(())
@ -115,12 +137,14 @@ fn run(t: &mut Activation, ds: Arc<Cap>, spec: HttpRouter) -> ActorResult {
let req = match language().parse::<http::HttpRequest>(&req) { Ok(v) => v, Err(_) => return Ok(()) }; let req = match language().parse::<http::HttpRequest>(&req) { Ok(v) => v, Err(_) => return Ok(()) };
let res = match res.value().to_embedded() { Ok(v) => v, Err(_) => return Ok(()) }; let res = match res.value().to_embedded() { Ok(v) => v, Err(_) => return Ok(()) };
tracing::trace!("Looking up handler for {:#?} in {:#?}", &req, &t.get(&routes));
let host_map = match t.get(&routes).get(&req.port) { let host_map = match t.get(&routes).get(&req.port) {
Some(host_map) => host_map, Some(host_map) => host_map,
None => return send_empty(t, res, 404, "Not found"), None => return send_empty(t, res, 404, "Not found"),
}; };
let methods = match try_hostname(host_map, http::HostPattern::Host(req.host.clone()), &req.path)? { let methods = match request_host(&req.host).and_then(|h| try_hostname(host_map, http::HostPattern::Host(h), &req.path).transpose()).transpose()? {
Some(methods) => methods, Some(methods) => methods,
None => match try_hostname(host_map, http::HostPattern::Any, &req.path)? { None => match try_hostname(host_map, http::HostPattern::Any, &req.path)? {
Some(methods) => methods, Some(methods) => methods,
@ -141,9 +165,7 @@ fn run(t: &mut Activation, ds: Arc<Cap>, spec: HttpRouter) -> ActorResult {
code: 405.into(), message: "Method Not Allowed".into() }); code: 405.into(), message: "Method Not Allowed".into() });
res.message(t, language(), &http::HttpResponse::Header { res.message(t, language(), &http::HttpResponse::Header {
name: "allow".into(), value: allowed }); name: "allow".into(), value: allowed });
res.message(t, language(), &http::HttpResponse::Done { return send_done(t, res);
chunk: Box::new(http::Chunk::Bytes(vec![])) });
return Ok(())
} }
} }
}; };
@ -151,21 +173,33 @@ fn run(t: &mut Activation, ds: Arc<Cap>, spec: HttpRouter) -> ActorResult {
if handlers.len() > 1 { if handlers.len() > 1 {
tracing::warn!(?req, "Too many handlers available"); tracing::warn!(?req, "Too many handlers available");
} }
let handler = handlers.first().expect("Nonempty handler set").clone(); let ActiveHandler { cap, terminated } = handlers.first().expect("Nonempty handler set").clone();
handler.assert(t, language(), &http::HttpContext { req, res: res.clone() }); tracing::trace!("Handler for {:?} is {:?}", &req, &cap);
t.dataflow(enclose!((terminated, req, res) move |t| {
if *t.get(&terminated) {
tracing::trace!("Handler for {:?} terminated", &req);
send_empty(t, &res, 500, "Internal Server Error")?;
}
Ok(())
}))?;
cap.assert(t, language(), &http::HttpContext { req, res: res.clone() });
Ok(()) Ok(())
}); });
Ok(()) Ok(())
} }
fn send_done(t: &mut Activation, res: &Arc<Cap>) -> ActorResult {
res.message(t, language(), &http::HttpResponse::Done {
chunk: Box::new(http::Chunk::Bytes(vec![])) });
Ok(())
}
fn send_empty(t: &mut Activation, res: &Arc<Cap>, code: u16, message: &str) -> ActorResult { fn send_empty(t: &mut Activation, res: &Arc<Cap>, code: u16, message: &str) -> ActorResult {
res.message(t, language(), &http::HttpResponse::Status { res.message(t, language(), &http::HttpResponse::Status {
code: code.into(), message: message.into() }); code: code.into(), message: message.into() });
res.message(t, language(), &http::HttpResponse::Done { send_done(t, res)
chunk: Box::new(http::Chunk::Bytes(vec![])) });
return Ok(())
} }
fn path_pattern_matches(path_pat: &http::PathPattern, path: &Vec<String>) -> bool { fn path_pattern_matches(path_pat: &http::PathPattern, path: &Vec<String>) -> bool {
@ -187,7 +221,10 @@ fn path_pattern_matches(path_pat: &http::PathPattern, path: &Vec<String>) -> boo
http::PathPatternElement::Rest => return true, http::PathPatternElement::Rest => return true,
} }
} }
true match path_iter.next() {
Some(_more) => false,
None => true,
}
} }
fn try_hostname<'table>( fn try_hostname<'table>(
@ -199,6 +236,7 @@ fn try_hostname<'table>(
None => Ok(None), None => Ok(None),
Some(path_table) => { Some(path_table) => {
for (path_pat, method_table) in path_table.iter() { for (path_pat, method_table) in path_table.iter() {
tracing::trace!("Checking path {:?} against pattern {:?}", &path, &path_pat);
if path_pattern_matches(path_pat, path) { if path_pattern_matches(path_pat, path) {
return Ok(Some(method_table)); return Ok(Some(method_table));
} }
@ -263,9 +301,7 @@ impl HttpStaticFileServer {
code: 301.into(), message: "Moved permanently".into() }); code: 301.into(), message: "Moved permanently".into() });
res.message(t, language(), &http::HttpResponse::Header { res.message(t, language(), &http::HttpResponse::Header {
name: "location".into(), value: format!("/{}/", req.path.join("/")) }); name: "location".into(), value: format!("/{}/", req.path.join("/")) });
res.message(t, language(), &http::HttpResponse::Done { return send_done(t, res);
chunk: Box::new(http::Chunk::Bytes(vec![])) });
return Ok(())
} else { } else {
let mut buf = Vec::new(); let mut buf = Vec::new();
fh.read_to_end(&mut buf)?; fh.read_to_end(&mut buf)?;
@ -286,6 +322,7 @@ impl HttpStaticFileServer {
} }
res.message(t, language(), &http::HttpResponse::Done { res.message(t, language(), &http::HttpResponse::Done {
chunk: Box::new(http::Chunk::Bytes(body)) }); chunk: Box::new(http::Chunk::Bytes(body)) });
Ok(()) Ok(())
} }
} }

View File

@ -15,24 +15,20 @@ use tokio::net::TcpListener;
use crate::language::language; use crate::language::language;
use crate::lifecycle; use crate::lifecycle;
use crate::protocol::detect_protocol; use crate::protocol::detect_protocol;
use crate::schemas::internal_services::{TcpWithHttp, TcpWithoutHttp, TcpRelayListener}; use crate::schemas::internal_services::TcpWithoutHttp;
use syndicate_macros::during; use syndicate_macros::during;
pub fn on_demand(t: &mut Activation, ds: Arc<Cap>) { pub fn on_demand(t: &mut Activation, ds: Arc<Cap>) {
t.spawn(Some(AnyValue::symbol("tcp_relay_listener")), move |t| { t.spawn(Some(AnyValue::symbol("tcp_relay_listener")), move |t| {
enclose!((ds) during!(t, ds, language(), <run-service $spec: TcpWithHttp::<AnyValue>>, |t: &mut Activation| {
spec.httpd.assert(t, language(), &syndicate::schemas::http::HttpListener { port: spec.addr.port.clone() });
run_supervisor(t, ds.clone(), TcpRelayListener::TcpWithHttp(Box::new(spec)))
}));
enclose!((ds) during!(t, ds, language(), <run-service $spec: TcpWithoutHttp::<AnyValue>>, |t| { enclose!((ds) during!(t, ds, language(), <run-service $spec: TcpWithoutHttp::<AnyValue>>, |t| {
run_supervisor(t, ds.clone(), TcpRelayListener::TcpWithoutHttp(Box::new(spec))) run_supervisor(t, ds.clone(), spec)
})); }));
Ok(()) Ok(())
}); });
} }
fn run_supervisor(t: &mut Activation, ds: Arc<Cap>, spec: TcpRelayListener) -> ActorResult { fn run_supervisor(t: &mut Activation, ds: Arc<Cap>, spec: TcpWithoutHttp) -> ActorResult {
Supervisor::start( Supervisor::start(
t, t,
Some(rec![AnyValue::symbol("relay"), language().unparse(&spec)]), Some(rec![AnyValue::symbol("relay"), language().unparse(&spec)]),
@ -41,18 +37,32 @@ fn run_supervisor(t: &mut Activation, ds: Arc<Cap>, spec: TcpRelayListener) -> A
enclose!((ds) move |t| enclose!((ds, spec) run(t, ds, spec)))) enclose!((ds) move |t| enclose!((ds, spec) run(t, ds, spec))))
} }
fn run(t: &mut Activation, ds: Arc<Cap>, spec: TcpRelayListener) -> ActorResult { fn run(t: &mut Activation, ds: Arc<Cap>, spec: TcpWithoutHttp) -> ActorResult {
lifecycle::terminate_on_service_restart(t, &ds, &spec); lifecycle::terminate_on_service_restart(t, &ds, &spec);
let (addr, gatekeeper, httpd) = match spec.clone() {
TcpRelayListener::TcpWithHttp(b) => { let httpd = t.named_field("httpd", None::<Arc<Cap>>);
let TcpWithHttp { addr, gatekeeper, httpd } = *b;
(addr, gatekeeper, Some(httpd)) {
} let ad = spec.addr.clone();
TcpRelayListener::TcpWithoutHttp(b) => { let ad2 = ad.clone();
let TcpWithoutHttp { addr, gatekeeper } = *b; let gk = spec.gatekeeper.clone();
(addr, gatekeeper, None) enclose!((ds, httpd) during!(t, ds, language(),
} <run-service <relay-listener #(&language().unparse(&ad)) #(&AnyValue::domain(gk)) $h>>, |t: &mut Activation| {
}; if let Some(h) = h.value().as_embedded().cloned() {
h.assert(t, language(), &syndicate::schemas::http::HttpListener { port: ad2.port.clone() });
*t.get_mut(&httpd) = Some(h.clone());
t.on_stop(enclose!((httpd) move |t| {
let f = t.get_mut(&httpd);
if *f == Some(h.clone()) { *f = None; }
Ok(())
}));
}
Ok(())
}));
}
let TcpWithoutHttp { addr, gatekeeper } = spec.clone();
let host = addr.host.clone(); let host = addr.host.clone();
let port = u16::try_from(&addr.port).map_err(|_| "Invalid TCP port number")?; let port = u16::try_from(&addr.port).map_err(|_| "Invalid TCP port number")?;
let facet = t.facet_ref(); let facet = t.facet_ref();
@ -83,6 +93,7 @@ fn run(t: &mut Activation, ds: Arc<Cap>, spec: TcpRelayListener) -> ActorResult
let account = Account::new(name.clone(), trace_collector.clone()); let account = Account::new(name.clone(), trace_collector.clone());
if !facet.activate( if !facet.activate(
&account, cause, enclose!((trace_collector, httpd) move |t| { &account, cause, enclose!((trace_collector, httpd) move |t| {
let httpd = t.get(&httpd).clone();
t.spawn(name, move |t| { t.spawn(name, move |t| {
Ok(t.linked_task(None, { Ok(t.linked_task(None, {
let facet = t.facet_ref(); let facet = t.facet_ref();
@ -91,7 +102,7 @@ fn run(t: &mut Activation, ds: Arc<Cap>, spec: TcpRelayListener) -> ActorResult
facet, facet,
stream, stream,
gatekeeper, gatekeeper,
httpd.map(|r| r.clone()), httpd,
addr, addr,
port).await?; port).await?;
Ok(LinkedTaskTermination::KeepFacet) Ok(LinkedTaskTermination::KeepFacet)

View File

@ -1,6 +1,6 @@
[package] [package]
name = "syndicate-tools" name = "syndicate-tools"
version = "0.16.0" version = "0.18.0"
authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"] authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"]
edition = "2018" edition = "2018"
@ -11,7 +11,7 @@ license = "Apache-2.0"
[dependencies] [dependencies]
preserves = "4.995" preserves = "4.995"
syndicate = { path = "../syndicate", version = "0.38.0"} syndicate = { path = "../syndicate", version = "0.40.0"}
clap = { version = "^4.0", features = ["derive"] } clap = { version = "^4.0", features = ["derive"] }
clap_complete = "^4.0" clap_complete = "^4.0"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "syndicate" name = "syndicate"
version = "0.38.0" version = "0.40.1"
authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"] authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"]
edition = "2018" edition = "2018"

View File

@ -11,6 +11,7 @@ use syndicate::during::entity;
use syndicate::dataspace::Dataspace; use syndicate::dataspace::Dataspace;
use syndicate::schemas::dataspace::Observe; use syndicate::schemas::dataspace::Observe;
use syndicate::schemas::dataspace_patterns as p; use syndicate::schemas::dataspace_patterns as p;
use syndicate::value::Map;
use syndicate::value::NestedValue; use syndicate::value::NestedValue;
use syndicate::value::Value; use syndicate::value::Value;
@ -88,11 +89,11 @@ pub fn bench_pub(c: &mut Criterion) {
.create_cap(t); .create_cap(t);
ds.assert(t, language(), &Observe { ds.assert(t, language(), &Observe {
pattern: p::Pattern::DBind(Box::new(p::DBind { pattern: p::Pattern::Bind {
pattern: p::Pattern::DLit(Box::new(p::DLit { pattern: Box::new(p::Pattern::Lit {
value: p::AnyAtom::Symbol("consumer".to_owned()), value: Box::new(p::AnyAtom::Symbol("consumer".to_owned())),
})), }),
})), },
observer: shutdown, observer: shutdown,
}); });
@ -110,24 +111,27 @@ pub fn bench_pub(c: &mut Criterion) {
ds.assert(t, &(), &AnyValue::symbol("consumer")); ds.assert(t, &(), &AnyValue::symbol("consumer"));
ds.assert(t, language(), &Observe { ds.assert(t, language(), &Observe {
pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec { pattern: p::Pattern::Group {
label: AnyValue::symbol("Says"), type_: Box::new(p::GroupType::Rec {
fields: vec![ label: AnyValue::symbol("Says"),
p::Pattern::DLit(Box::new(p::DLit { }),
value: p::AnyAtom::String("bench_pub".to_owned()), entries: Map::from([
})), (p::_Any::new(0), p::Pattern::Lit {
p::Pattern::DBind(Box::new(p::DBind { value: Box::new(p::AnyAtom::String("bench_pub".to_owned())),
pattern: p::Pattern::DDiscard(Box::new(p::DDiscard)), }),
})), (p::_Any::new(1), p::Pattern::Bind {
]})), pattern: Box::new(p::Pattern::Discard),
}),
]),
},
observer: receiver, observer: receiver,
}); });
ds.assert(t, language(), &Observe { ds.assert(t, language(), &Observe {
pattern: p::Pattern::DBind(Box::new(p::DBind { pattern: p::Pattern::Bind {
pattern: p::Pattern::DLit(Box::new(p::DLit { pattern: Box::new(p::Pattern::Lit {
value: p::AnyAtom::Bool(true), value: Box::new(p::AnyAtom::Bool(true)),
})), }),
})), },
observer: shutdown, observer: shutdown,
}); });

View File

@ -2,9 +2,9 @@
tcp-remote„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³ SignedInteger„„„„„³ TcpPeerInfo´³rec´³lit³tcp-peer„´³tupleµ´³named³handle´³embedded³any„„´³named³local´³refµ„³TcpLocal„„´³named³remote´³refµ„³ TcpRemote„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³http„´³schema·³version°³ definitions·³Chunk´³orµµ±string´³atom³String„„µ±bytes´³atom³ tcp-remote„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³ SignedInteger„„„„„³ TcpPeerInfo´³rec´³lit³tcp-peer„´³tupleµ´³named³handle´³embedded³any„„´³named³local´³refµ„³TcpLocal„„´³named³remote´³refµ„³ TcpRemote„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³http„´³schema·³version°³ definitions·³Chunk´³orµµ±string´³atom³String„„µ±bytes´³atom³
ByteString„„„„³Headers´³dictof´³atom³Symbol„´³atom³String„„³MimeType´³atom³Symbol„³ ByteString„„„„³Headers´³dictof´³atom³Symbol„´³atom³String„„³MimeType´³atom³Symbol„³
QueryValue´³orµµ±string´³atom³String„„µ±file´³rec´³lit³file„´³tupleµ´³named³filename´³atom³String„„´³named³headers´³refµ„³Headers„„´³named³body´³atom³ QueryValue´³orµµ±string´³atom³String„„µ±file´³rec´³lit³file„´³tupleµ´³named³filename´³atom³String„„´³named³headers´³refµ„³Headers„„´³named³body´³atom³
ByteString„„„„„„„„³ HostPattern´³orµµ±host´³atom³String„„µ±any´³lit€„„„„³ HttpBinding´³rec´³lit³ http-bind„´³tupleµ´³named³host´³refµ„³ HostPattern„„´³named³port´³atom³ SignedInteger„„´³named³method´³refµ„³ MethodPattern„„´³named³path´³refµ„³ PathPattern„„´³named³handler´³embedded´³refµ„³ HttpRequest„„„„„„³ HttpContext´³rec´³lit³request„´³tupleµ´³named³req´³refµ„³ HttpRequest„„´³named³res´³embedded´³refµ„³ HttpResponse„„„„„„³ HttpRequest´³rec´³lit³ http-request„´³tupleµ´³named³sequenceNumber´³atom³ SignedInteger„„´³named³host´³atom³String„„´³named³port´³atom³ SignedInteger„„´³named³method´³atom³Symbol„„´³named³path´³seqof´³atom³String„„„´³named³headers´³refµ„³Headers„„´³named³query´³dictof´³atom³Symbol„´³seqof´³refµ„³ ByteString„„„„„„„„³ HostPattern´³orµµ±host´³atom³String„„µ±any´³lit€„„„„³ HttpBinding´³rec´³lit³ http-bind„´³tupleµ´³named³host´³refµ„³ HostPattern„„´³named³port´³atom³ SignedInteger„„´³named³method´³refµ„³ MethodPattern„„´³named³path´³refµ„³ PathPattern„„´³named³handler´³embedded´³refµ„³ HttpRequest„„„„„„³ HttpContext´³rec´³lit³request„´³tupleµ´³named³req´³refµ„³ HttpRequest„„´³named³res´³embedded´³refµ„³ HttpResponse„„„„„„³ HttpRequest´³rec´³lit³ http-request„´³tupleµ´³named³sequenceNumber´³atom³ SignedInteger„„´³named³host´³refµ„³ RequestHost„„´³named³port´³atom³ SignedInteger„„´³named³method´³atom³Symbol„„´³named³path´³seqof´³atom³String„„„´³named³headers´³refµ„³Headers„„´³named³query´³dictof´³atom³Symbol„´³seqof´³refµ„³
QueryValue„„„„´³named³body´³refµ„³ RequestBody„„„„„³ HttpService´³rec´³lit³ http-service„´³tupleµ´³named³host´³refµ„³ HostPattern„„´³named³port´³atom³ SignedInteger„„´³named³method´³refµ„³ MethodPattern„„´³named³path´³refµ„³ PathPattern„„„„„³ PathPattern´³seqof´³refµ„³PathPatternElement„„³ RequestBody´³orµµ±present´³atom³ QueryValue„„„„´³named³body´³refµ„³ RequestBody„„„„„³ HttpService´³rec´³lit³ http-service„´³tupleµ´³named³host´³refµ„³ HostPattern„„´³named³port´³atom³ SignedInteger„„´³named³method´³refµ„³ MethodPattern„„´³named³path´³refµ„³ PathPattern„„„„„³ PathPattern´³seqof´³refµ„³PathPatternElement„„³ RequestBody´³orµµ±absent´³lit€„„µ±present´³atom³
ByteString„„µ±absent´³lit€„„„„³ HttpListener´³rec´³lit³ http-listener„´³tupleµ´³named³port´³atom³ SignedInteger„„„„„³ HttpResponse´³orµµ±status´³rec´³lit³status„´³tupleµ´³named³code´³atom³ SignedInteger„„´³named³message´³atom³String„„„„„„µ±header´³rec´³lit³header„´³tupleµ´³named³name´³atom³Symbol„„´³named³value´³atom³String„„„„„„µ±chunk´³rec´³lit³chunk„´³tupleµ´³named³chunk´³refµ„³Chunk„„„„„„µ±done´³rec´³lit³done„´³tupleµ´³named³chunk´³refµ„³Chunk„„„„„„„„³ MethodPattern´³orµµ±any´³lit€„„µ±specific´³atom³Symbol„„„„³PathPatternElement´³orµµ±label´³atom³String„„µ±wildcard´³lit³_„„µ±rest´³lit³...„„„„„³ embeddedType€„„µ³noise„´³schema·³version°³ definitions·³Packet´³orµµ±complete´³atom³ ByteString„„„„³ RequestHost´³orµµ±absent´³lit€„„µ±present´³atom³String„„„„³ HttpListener´³rec´³lit³ http-listener„´³tupleµ´³named³port´³atom³ SignedInteger„„„„„³ HttpResponse´³orµµ±status´³rec´³lit³status„´³tupleµ´³named³code´³atom³ SignedInteger„„´³named³message´³atom³String„„„„„„µ±header´³rec´³lit³header„´³tupleµ´³named³name´³atom³Symbol„„´³named³value´³atom³String„„„„„„µ±chunk´³rec´³lit³chunk„´³tupleµ´³named³chunk´³refµ„³Chunk„„„„„„µ±done´³rec´³lit³done„´³tupleµ´³named³chunk´³refµ„³Chunk„„„„„„„„³ MethodPattern´³orµµ±any´³lit€„„µ±specific´³atom³Symbol„„„„³PathPatternElement´³orµµ±label´³atom³String„„µ±wildcard´³lit³_„„µ±rest´³lit³...„„„„„³ embeddedType€„„µ³noise„´³schema·³version°³ definitions·³Packet´³orµµ±complete´³atom³
ByteString„„µ± ByteString„„µ±
fragmented´³seqof´³atom³ fragmented´³seqof´³atom³
ByteString„„„„„³ Initiator´³rec´³lit³ initiator„´³tupleµ´³named³initiatorSession´³embedded´³refµ„³Packet„„„„„„³ NoiseSpec´³andµ´³dict·³key´³named³key´³atom³ ByteString„„„„„³ Initiator´³rec´³lit³ initiator„´³tupleµ´³named³initiatorSession´³embedded´³refµ„³Packet„„„„„„³ NoiseSpec´³andµ´³dict·³key´³named³key´³atom³
@ -38,7 +38,7 @@ Parameters
Parameters„³SturdyDescriptionDetail´³dict·³key´³named³key´³atom³ Parameters„³SturdyDescriptionDetail´³dict·³key´³named³key´³atom³
ByteString„„³oid´³named³oid³any„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³worker„´³schema·³version°³ definitions·³Instance´³rec´³lit³Instance„´³tupleµ´³named³name´³atom³String„„´³named³argument³any„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³service„´³schema·³version°³ definitions·³State´³orµµ±started´³lit³started„„µ±ready´³lit³ready„„µ±failed´³lit³failed„„µ±complete´³lit³complete„„µ± userDefined³any„„„³ ByteString„„³oid´³named³oid³any„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³worker„´³schema·³version°³ definitions·³Instance´³rec´³lit³Instance„´³tupleµ´³named³name´³atom³String„„´³named³argument³any„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³service„´³schema·³version°³ definitions·³State´³orµµ±started´³lit³started„„µ±ready´³lit³ready„„µ±failed´³lit³failed„„µ±complete´³lit³complete„„µ± userDefined³any„„„³
RunService´³rec´³lit³ run-service„´³tupleµ´³named³ serviceName³any„„„„³ ServiceState´³rec´³lit³ service-state„´³tupleµ´³named³ serviceName³any„´³named³state´³refµ„³State„„„„„³ ServiceObject´³rec´³lit³service-object„´³tupleµ´³named³ serviceName³any„´³named³object³any„„„„³RequireService´³rec´³lit³require-service„´³tupleµ´³named³ serviceName³any„„„„³RestartService´³rec´³lit³restart-service„´³tupleµ´³named³ serviceName³any„„„„³ServiceDependency´³rec´³lit³ RunService´³rec´³lit³ run-service„´³tupleµ´³named³ serviceName³any„„„„³ ServiceState´³rec´³lit³ service-state„´³tupleµ´³named³ serviceName³any„´³named³state´³refµ„³State„„„„„³ ServiceObject´³rec´³lit³service-object„´³tupleµ´³named³ serviceName³any„´³named³object³any„„„„³RequireService´³rec´³lit³require-service„´³tupleµ´³named³ serviceName³any„„„„³RestartService´³rec´³lit³restart-service„´³tupleµ´³named³ serviceName³any„„„„³ServiceDependency´³rec´³lit³
depends-on„´³tupleµ´³named³depender³any„´³named³dependee´³refµ„³ ServiceState„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³protocol„´³schema·³version°³ definitions·³Oid´³atom³ SignedInteger„³Sync´³rec´³lit³S„´³tupleµ´³named³peer´³embedded´³lit<69>„„„„„„³Turn´³seqof´³refµ„³ TurnEvent„„³Error´³rec´³lit³error„´³tupleµ´³named³message´³atom³String„„´³named³detail³any„„„„³Event´³orµµ±Assert´³refµ„³Assert„„µ±Retract´³refµ„³Retract„„µ±Message´³refµ„³Message„„µ±Sync´³refµ„³Sync„„„„³Assert´³rec´³lit³A„´³tupleµ´³named³ assertion´³refµ„³ Assertion„„´³named³handle´³refµ„³Handle„„„„„³Handle´³atom³ SignedInteger„³Packet´³orµµ±Turn´³refµ„³Turn„„µ±Error´³refµ„³Error„„µ± Extension´³refµ„³ Extension„„„„³Message´³rec´³lit³M„´³tupleµ´³named³body´³refµ„³ Assertion„„„„„³Retract´³rec´³lit³R„´³tupleµ´³named³handle´³refµ„³Handle„„„„„³ Assertion³any³ Extension´³rec´³named³label³any„´³named³fields´³seqof³any„„„³ TurnEvent´³tupleµ´³named³oid´³refµ„³Oid„„´³named³event´³refµ„³Event„„„„„³ embeddedType€„„µ³ dataspace„´³schema·³version°³ definitions·³Observe´³rec´³lit³Observe„´³tupleµ´³named³pattern´³refµ³dataspacePatterns„³Pattern„„´³named³observer´³embedded³any„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³ depends-on„´³tupleµ´³named³depender³any„´³named³dependee´³refµ„³ ServiceState„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³protocol„´³schema·³version°³ definitions·³Nop´³lit€„³Oid´³atom³ SignedInteger„³Sync´³rec´³lit³S„´³tupleµ´³named³peer´³embedded´³lit<69>„„„„„„³Turn´³seqof´³refµ„³ TurnEvent„„³Error´³rec´³lit³error„´³tupleµ´³named³message´³atom³String„„´³named³detail³any„„„„³Event´³orµµ±Assert´³refµ„³Assert„„µ±Retract´³refµ„³Retract„„µ±Message´³refµ„³Message„„µ±Sync´³refµ„³Sync„„„„³Assert´³rec´³lit³A„´³tupleµ´³named³ assertion´³refµ„³ Assertion„„´³named³handle´³refµ„³Handle„„„„„³Handle´³atom³ SignedInteger„³Packet´³orµµ±Turn´³refµ„³Turn„„µ±Error´³refµ„³Error„„µ± Extension´³refµ„³ Extension„„µ±Nop´³refµ„³Nop„„„„³Message´³rec´³lit³M„´³tupleµ´³named³body´³refµ„³ Assertion„„„„„³Retract´³rec´³lit³R„´³tupleµ´³named³handle´³refµ„³Handle„„„„„³ Assertion³any³ Extension´³rec´³named³label³any„´³named³fields´³seqof³any„„„³ TurnEvent´³tupleµ´³named³oid´³refµ„³Oid„„´³named³event´³refµ„³Event„„„„„³ embeddedType€„„µ³ dataspace„´³schema·³version°³ definitions·³Observe´³rec´³lit³Observe„´³tupleµ´³named³pattern´³refµ³dataspacePatterns„³Pattern„„´³named³observer´³embedded³any„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³
gatekeeper„´³schema·³version°³ definitions·³Bind´³rec´³lit³bind„´³tupleµ´³named³ description´³refµ„³ Description„„´³named³target´³embedded³any„„´³named³observer´³refµ„³ BindObserver„„„„„³Step´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Bound´³orµµ±bound´³rec´³lit³bound„´³tupleµ´³named³pathStep´³refµ„³PathStep„„„„„„µ±Rejected´³refµ„³Rejected„„„„³Route´³rec´³lit³route„´³ tuplePrefixµ´³named³ gatekeeper„´³schema·³version°³ definitions·³Bind´³rec´³lit³bind„´³tupleµ´³named³ description´³refµ„³ Description„„´³named³target´³embedded³any„„´³named³observer´³refµ„³ BindObserver„„„„„³Step´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Bound´³orµµ±bound´³rec´³lit³bound„´³tupleµ´³named³pathStep´³refµ„³PathStep„„„„„„µ±Rejected´³refµ„³Rejected„„„„³Route´³rec´³lit³route„´³ tuplePrefixµ´³named³
transports´³seqof³any„„„´³named³ pathSteps´³seqof´³refµ„³PathStep„„„„„³Resolve´³rec´³lit³resolve„´³tupleµ´³named³step´³refµ„³Step„„´³named³observer´³embedded´³refµ„³Resolved„„„„„„³PathStep´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Rejected´³rec´³lit³rejected„´³tupleµ´³named³detail³any„„„„³Resolved´³orµµ±accepted´³rec´³lit³accepted„´³tupleµ´³named³responderSession´³embedded³any„„„„„„µ±Rejected´³refµ„³Rejected„„„„³ Description´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³ ResolvePath´³rec´³lit³ resolve-path„´³tupleµ´³named³route´³refµ„³Route„„´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„³ BindObserver´³orµµ±present´³embedded´³refµ„³Bound„„„µ±absent´³lit€„„„„³ForceDisconnect´³rec´³lit³force-disconnect„´³tupleµ„„„³ResolvedPathStep´³rec´³lit³ path-step„´³tupleµ´³named³origin´³embedded´³refµ„³Resolve„„„´³named³pathStep´³refµ„³PathStep„„´³named³resolved´³refµ„³Resolved„„„„„³TransportControl´³refµ„³ForceDisconnect„³TransportConnection´³rec´³lit³connect-transport„´³tupleµ´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³transportAddress„´³schema·³version°³ definitions·³Tcp´³rec´³lit³tcp„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³ SignedInteger„„„„„³Unix´³rec´³lit³unix„´³tupleµ´³named³path´³atom³String„„„„„³Stdio´³rec´³lit³stdio„´³tupleµ„„„³ WebSocket´³rec´³lit³ws„´³tupleµ´³named³url´³atom³String„„„„„„³ embeddedType€„„µ³dataspacePatterns„´³schema·³version°³ definitions·³DLit´³rec´³lit³lit„´³tupleµ´³named³value´³refµ„³AnyAtom„„„„„³DBind´³rec´³lit³bind„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„³AnyAtom´³orµµ±bool´³atom³Boolean„„µ±double´³atom³Double„„µ±int´³atom³ SignedInteger„„µ±string´³atom³String„„µ±bytes´³atom³ transports´³seqof³any„„„´³named³ pathSteps´³seqof´³refµ„³PathStep„„„„„³Resolve´³rec´³lit³resolve„´³tupleµ´³named³step´³refµ„³Step„„´³named³observer´³embedded´³refµ„³Resolved„„„„„„³PathStep´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Rejected´³rec´³lit³rejected„´³tupleµ´³named³detail³any„„„„³Resolved´³orµµ±accepted´³rec´³lit³accepted„´³tupleµ´³named³responderSession´³embedded³any„„„„„„µ±Rejected´³refµ„³Rejected„„„„³ Description´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³ ResolvePath´³rec´³lit³ resolve-path„´³tupleµ´³named³route´³refµ„³Route„„´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„³ BindObserver´³orµµ±present´³embedded´³refµ„³Bound„„„µ±absent´³lit€„„„„³ForceDisconnect´³rec´³lit³force-disconnect„´³tupleµ„„„³ResolvedPathStep´³rec´³lit³ path-step„´³tupleµ´³named³origin´³embedded´³refµ„³Resolve„„„´³named³pathStep´³refµ„³PathStep„„´³named³resolved´³refµ„³Resolved„„„„„³TransportControl´³refµ„³ForceDisconnect„³TransportConnection´³rec´³lit³connect-transport„´³tupleµ´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³transportAddress„´³schema·³version°³ definitions·³Tcp´³rec´³lit³tcp„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³ SignedInteger„„„„„³Unix´³rec´³lit³unix„´³tupleµ´³named³path´³atom³String„„„„„³Stdio´³rec´³lit³stdio„´³tupleµ„„„³ WebSocket´³rec´³lit³ws„´³tupleµ´³named³url´³atom³String„„„„„„³ embeddedType€„„µ³dataspacePatterns„´³schema·³version°³ definitions·³AnyAtom´³orµµ±bool´³atom³Boolean„„µ±double´³atom³Double„„µ±int´³atom³ SignedInteger„„µ±string´³atom³String„„µ±bytes´³atom³
ByteString„„µ±symbol´³atom³Symbol„„µ±embedded´³embedded³any„„„„³Pattern´³orµµ±DDiscard´³refµ„³DDiscard„„µ±DBind´³refµ„³DBind„„µ±DLit´³refµ„³DLit„„µ± DCompound´³refµ„³ DCompound„„„„³DDiscard´³rec´³lit³_„´³tupleµ„„„³ DCompound´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label³any„´³named³fields´³seqof´³refµ„³Pattern„„„„„„„µ±arr´³rec´³lit³arr„´³tupleµ´³named³items´³seqof´³refµ„³Pattern„„„„„„„µ±dict´³rec´³lit³dict„´³tupleµ´³named³entries´³dictof³any´³refµ„³Pattern„„„„„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„„„ ByteString„„µ±symbol´³atom³Symbol„„µ±embedded´³embedded³any„„„„³Pattern´³orµµ±discard´³rec´³lit³_„´³tupleµ„„„„µ±bind´³rec´³lit³bind„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„„µ±lit´³rec´³lit³lit„´³tupleµ´³named³value´³refµ„³AnyAtom„„„„„„µ±group´³rec´³lit³group„´³tupleµ´³named³type´³refµ„³ GroupType„„´³named³entries´³dictof³any´³refµ„³Pattern„„„„„„„„„³ GroupType´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label³any„„„„„µ±arr´³rec´³lit³arr„´³tupleµ„„„„µ±dict´³rec´³lit³dict„´³tupleµ„„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„„„

View File

@ -1,15 +1,23 @@
version 1 . version 1 .
embeddedType EntityRef.Cap . embeddedType EntityRef.Cap .
# Dataspace patterns: a sublanguage of attenuation patterns. # Dataspace patterns: *almost* a sublanguage of attenuation patterns.
Pattern = DDiscard / DBind / DLit / DCompound . #
# One key difference is that Dataspace patterns are extensible, in that
# they ignore fields not mentioned in group patterns.
DDiscard = <_>. Pattern =
DBind = <bind @pattern Pattern>. / @discard <_>
DLit = <lit @value AnyAtom>. / <bind @pattern Pattern>
DCompound = <rec @label any @fields [Pattern ...]> / <lit @value AnyAtom>
/ <arr @items [Pattern ...]> / <group @type GroupType @entries { any: Pattern ...:... }>
/ <dict @entries { any: Pattern ...:... }> . .
GroupType =
/ <rec @label any>
/ <arr>
/ <dict>
.
AnyAtom = AnyAtom =
/ @bool bool / @bool bool

View File

@ -21,7 +21,7 @@ MethodPattern = @any #f / @specific @"Lowercase" symbol .
# Assertion in driver DS # Assertion in driver DS
HttpRequest = <http-request HttpRequest = <http-request
@sequenceNumber int @sequenceNumber int
@host string @host RequestHost
@port int @port int
@method @"Lowercase" symbol @method @"Lowercase" symbol
@path [string ...] @path [string ...]
@ -31,14 +31,25 @@ HttpRequest = <http-request
Headers = {@"Lowercase" symbol: string ...:...} . Headers = {@"Lowercase" symbol: string ...:...} .
QueryValue = @string string / <file @filename string @headers Headers @body bytes> . QueryValue = @string string / <file @filename string @headers Headers @body bytes> .
RequestBody = @present bytes / @absent #f . RequestBody = @absent #f / @present bytes .
RequestHost = @absent #f / @present string .
# Assertion to handler entity # Assertion to handler entity
HttpContext = <request @req HttpRequest @res #:HttpResponse> . HttpContext = <request @req HttpRequest @res #:HttpResponse> .
# HttpResponse protocol. Delivered to the `res` ref in `HttpContext`.
#
# (status | header)* . chunk* . done
#
# Done triggers completion of the response and retraction of the frame by the peer. If the
# HttpBinding responsible for the request is withdrawn mid-way through a response (i.e. when
# chunked transfer is used and at least one chunk has been sent) the request is abruptly
# closed; if it is withdrawn at any other moment in the lifetime of the request, a 500 Internal
# Server Error is send to the client.
#
@<TODO "trailers?"> @<TODO "trailers?">
# Messages
HttpResponse = HttpResponse =
# Messages.
/ <status @code int @message string> / <status @code int @message string>
/ <header @name symbol @value string> / <header @name symbol @value string>
/ <chunk @chunk Chunk> / <chunk @chunk Chunk>

View File

@ -60,7 +60,7 @@ NoisePreSharedKeys = @present { preSharedKeys: [bytes ...] } / @invalid { preSha
# complete Noise "transport message"; when `complete`, the whole thing is likewise a complete # complete Noise "transport message"; when `complete`, the whole thing is likewise a complete
# "transport message". # "transport message".
# #
# Retraction of the `Introduction` ends the session from the initiator-side; retraction of the # Retraction of the `Initiator` ends the session from the initiator-side; retraction of the
# `<accepted ...>` assertion ends the session from the responder-side. # `<accepted ...>` assertion ends the session from the responder-side.
SessionItem = Initiator / Packet . SessionItem = Initiator / Packet .

View File

@ -1,8 +1,9 @@
version 1 . version 1 .
Packet = Turn / Error / Extension . Packet = Turn / Error / Extension / Nop .
Extension = <<rec> @label any @fields [any ...]> . Extension = <<rec> @label any @fields [any ...]> .
Nop = #f .
Error = <error @message string @detail any>. Error = <error @message string @detail any>.

View File

@ -1214,6 +1214,8 @@ impl Activation {
// just drop 'em so they don't run next time // just drop 'em so they don't run next time
std::mem::take(&mut self.commit_actions); std::mem::take(&mut self.commit_actions);
} }
self.single_queue = None;
self.multiple_queues = None;
tracing::trace!("Activation::rollback complete"); tracing::trace!("Activation::rollback complete");
} }

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use crate::schemas::dataspace_patterns::*; use crate::schemas::dataspace_patterns::*;
use super::language; use super::language;
@ -8,23 +10,25 @@ use preserves::value::Record;
use preserves::value::Value; use preserves::value::Value;
use preserves_schema::Codec; use preserves_schema::Codec;
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)] pub type PathStep = _Any;
pub enum PathStep {
Index(usize),
Key(_Any),
}
pub type Path = Vec<PathStep>; pub type Path = Vec<PathStep>;
pub type Paths = Vec<Path>; pub type Paths = Vec<Path>;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct ConstantPositions {
pub with_values: Paths,
pub required_to_exist: Paths,
}
struct Analyzer { struct Analyzer {
pub const_paths: Paths, pub const_paths: Paths,
pub const_values: Vec<_Any>, pub const_values: Vec<_Any>,
pub checked_paths: Paths,
pub capture_paths: Paths, pub capture_paths: Paths,
} }
pub struct PatternAnalysis { pub struct PatternAnalysis {
pub const_paths: Paths, pub const_positions: Arc<ConstantPositions>,
pub const_values: _Any, pub const_values: _Any,
pub capture_paths: Paths, pub capture_paths: Paths,
} }
@ -38,11 +42,15 @@ impl PatternAnalysis {
let mut analyzer = Analyzer { let mut analyzer = Analyzer {
const_paths: Vec::new(), const_paths: Vec::new(),
const_values: Vec::new(), const_values: Vec::new(),
checked_paths: Vec::new(),
capture_paths: Vec::new(), capture_paths: Vec::new(),
}; };
analyzer.walk(&mut Vec::new(), p); analyzer.walk(&mut Vec::new(), p);
PatternAnalysis { PatternAnalysis {
const_paths: analyzer.const_paths, const_positions: Arc::new(ConstantPositions {
with_values: analyzer.const_paths,
required_to_exist: analyzer.checked_paths,
}),
const_values: _Any::new(analyzer.const_values), const_values: _Any::new(analyzer.const_values),
capture_paths: analyzer.capture_paths, capture_paths: analyzer.capture_paths,
} }
@ -58,34 +66,21 @@ impl Analyzer {
fn walk(&mut self, path: &mut Path, p: &Pattern) { fn walk(&mut self, path: &mut Path, p: &Pattern) {
match p { match p {
Pattern::DCompound(b) => match &**b { Pattern::Group { entries, .. } => {
DCompound::Rec { fields, .. } => { for (k, p) in entries {
for (i, p) in fields.iter().enumerate() { self.walk_step(path, k.clone(), p)
self.walk_step(path, PathStep::Index(i), p);
}
}
DCompound::Arr { items, .. } => {
for (i, p) in items.iter().enumerate() {
self.walk_step(path, PathStep::Index(i), p);
}
}
DCompound::Dict { entries, .. } => {
for (k, p) in entries {
self.walk_step(path, PathStep::Key(k.clone()), p);
}
} }
} }
Pattern::DBind(b) => { Pattern::Bind { pattern } => {
let DBind { pattern, .. } = &**b;
self.capture_paths.push(path.clone()); self.capture_paths.push(path.clone());
self.walk(path, pattern) self.walk(path, &**pattern);
} }
Pattern::DDiscard(_) => Pattern::Discard => {
(), self.checked_paths.push(path.clone());
Pattern::DLit(b) => { }
let DLit { value } = &**b; Pattern::Lit { value } => {
self.const_paths.push(path.clone()); self.const_paths.push(path.clone());
self.const_values.push(language().unparse(value)); self.const_values.push(language().unparse(&**value));
} }
} }
} }
@ -109,52 +104,47 @@ impl PatternMatcher {
} }
} }
fn run_seq<'a, F: 'a + Fn(usize) -> &'a _Any>(&mut self, entries: &Map<_Any, Pattern<_Any>>, values: F) -> bool {
for (k, p) in entries {
match k.value().as_usize() {
None => return false,
Some(i) => if !self.run(p, values(i)) {
return false;
}
}
}
true
}
fn run(&mut self, pattern: &Pattern<_Any>, value: &_Any) -> bool { fn run(&mut self, pattern: &Pattern<_Any>, value: &_Any) -> bool {
match pattern { match pattern {
Pattern::DDiscard(_) => true, Pattern::Discard => true,
Pattern::DBind(b) => { Pattern::Bind { pattern } => {
self.captures.push(value.clone()); self.captures.push(value.clone());
self.run(&b.pattern, value) self.run(&**pattern, value)
} }
Pattern::DLit(b) => value == &language().unparse(&b.value), Pattern::Lit { value: expected } => value == &language().unparse(&**expected),
Pattern::DCompound(b) => match &**b { Pattern::Group { type_, entries } => match &**type_ {
DCompound::Rec { label, fields } => { GroupType::Rec { label } => {
match value.value().as_record(Some(fields.len())) { match value.value().as_record(None) {
None => false, None => false,
Some(r) => { Some(r) =>
if r.label() != label { r.label() == label &&
return false; self.run_seq(entries, |i| &r.fields()[i])
}
for (i, p) in fields.iter().enumerate() {
if !self.run(p, &r.fields()[i]) {
return false;
}
}
true
}
} }
} }
DCompound::Arr { items } => { GroupType::Arr => {
match value.value().as_sequence() { match value.value().as_sequence() {
None => false, None => false,
Some(vs) => { Some(vs) =>
if vs.len() != items.len() { self.run_seq(entries, |i| &vs[i])
return false;
}
for (i, p) in items.iter().enumerate() {
if !self.run(p, &vs[i]) {
return false;
}
}
true
}
} }
} }
DCompound::Dict { entries: expected_entries } => { GroupType::Dict => {
match value.value().as_dictionary() { match value.value().as_dictionary() {
None => false, None => false,
Some(actual_entries) => { Some(actual_entries) => {
for (k, p) in expected_entries.iter() { for (k, p) in entries {
if !actual_entries.get(k).map(|v| self.run(p, v)).unwrap_or(false) { if !actual_entries.get(k).map(|v| self.run(p, v)).unwrap_or(false) {
return false; return false;
} }
@ -170,42 +160,68 @@ impl PatternMatcher {
pub fn lift_literal(v: &_Any) -> Pattern { pub fn lift_literal(v: &_Any) -> Pattern {
match v.value() { match v.value() {
Value::Record(r) => Pattern::DCompound(Box::new(DCompound::Rec { Value::Record(r) => Pattern::Group {
label: r.label().clone(), type_: Box::new(GroupType::Rec { label: r.label().clone() }),
fields: r.fields().iter().map(lift_literal).collect(), entries: r.fields().iter().enumerate()
})), .map(|(i, v)| (_Any::new(i), lift_literal(v)))
Value::Sequence(items) => Pattern::DCompound(Box::new(DCompound::Arr { .collect(),
items: items.iter().map(lift_literal).collect(), },
})), Value::Sequence(items) => Pattern::Group {
type_: Box::new(GroupType::Arr),
entries: items.iter().enumerate()
.map(|(i, v)| (_Any::new(i), lift_literal(v)))
.collect(),
},
Value::Set(_members) => panic!("Cannot express literal set in pattern"), Value::Set(_members) => panic!("Cannot express literal set in pattern"),
Value::Dictionary(entries) => Pattern::DCompound(Box::new(DCompound::Dict { Value::Dictionary(entries) => Pattern::Group {
entries: entries.iter().map(|(k, v)| (k.clone(), lift_literal(v))).collect(), type_: Box::new(GroupType::Dict),
})), entries: entries.iter()
_other => Pattern::DLit(Box::new(DLit { .map(|(k, v)| (k.clone(), lift_literal(v)))
value: language().parse(v).expect("Non-compound datum can be converted to AnyAtom"), .collect(),
})), },
_other => Pattern::Lit {
value: Box::new(language().parse(v).expect("Non-compound datum can be converted to AnyAtom")),
},
} }
} }
const DISCARD: Pattern = Pattern::Discard;
pub fn pattern_seq_from_dictionary(entries: &Map<_Any, Pattern>) -> Option<Vec<&Pattern>> {
let mut max_k: Option<usize> = None;
for k in entries.keys() {
max_k = max_k.max(Some(k.value().as_usize()?));
}
let mut seq = vec![];
if let Some(max_k) = max_k {
seq.reserve(max_k + 1);
for i in 0..=max_k {
seq.push(entries.get(&_Any::new(i)).unwrap_or(&DISCARD));
}
}
return Some(seq);
}
fn drop_literal_entries_seq(mut seq: Vec<_Any>, entries: &Map<_Any, Pattern>) -> Option<Vec<_Any>> {
for p in pattern_seq_from_dictionary(entries)?.into_iter() {
seq.push(drop_literal(p)?);
}
Some(seq)
}
pub fn drop_literal(p: &Pattern) -> Option<_Any> { pub fn drop_literal(p: &Pattern) -> Option<_Any> {
match p { match p {
Pattern::DCompound(b) => match &**b { Pattern::Group { type_, entries } => match &**type_ {
DCompound::Rec { label, fields } => { GroupType::Rec { label } =>
let mut r = vec![label.clone()]; Some(Value::Record(Record(drop_literal_entries_seq(vec![label.clone()], entries)?)).wrap()),
for f in fields.iter() { GroupType::Arr =>
r.push(drop_literal(f)?); Some(Value::Sequence(drop_literal_entries_seq(vec![], entries)?).wrap()),
} GroupType::Dict =>
Some(Value::Record(Record(r)).wrap()) Some(Value::Dictionary(entries.iter()
} .map(|(k, p)| Some((k.clone(), drop_literal(p)?)))
DCompound::Arr { items } => .collect::<Option<Map<_Any, _Any>>>()?).wrap()),
Some(Value::Sequence(items.iter().map(drop_literal)
.collect::<Option<Vec<_Any>>>()?).wrap()),
DCompound::Dict { entries } =>
Some(Value::Dictionary(entries.iter()
.map(|(k, p)| Some((k.clone(), drop_literal(p)?)))
.collect::<Option<Map<_Any, _Any>>>()?).wrap()),
}, },
Pattern::DLit(b) => Some(language().unparse(&b.value)), Pattern::Lit { value } => Some(language().unparse(&**value)),
_ => None, _ => None,
} }
} }

View File

@ -385,6 +385,10 @@ impl TunnelRelay {
tracing::info!(?label, ?fields, "received Extension from peer"); tracing::info!(?label, ?fields, "received Extension from peer");
Ok(()) Ok(())
} }
P::Packet::Nop(_b) => {
tracing::trace!("received Nop from peer");
Ok(())
}
P::Packet::Error(b) => { P::Packet::Error(b) => {
tracing::info!(message = ?b.message.clone(), tracing::info!(message = ?b.message.clone(),
detail = ?b.detail.clone(), detail = ?b.detail.clone(),

View File

@ -16,19 +16,12 @@ use crate::actor::Activation;
use crate::actor::Handle; use crate::actor::Handle;
use crate::actor::Cap; use crate::actor::Cap;
use crate::schemas::dataspace_patterns as ds; use crate::schemas::dataspace_patterns as ds;
use crate::pattern::{self, PathStep, Path, Paths}; use crate::pattern::{self, ConstantPositions, PathStep, Path, Paths};
type Bag<A> = bag::BTreeBag<A>; type Bag<A> = bag::BTreeBag<A>;
type Captures = AnyValue; type Captures = AnyValue;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
enum Guard {
Rec(AnyValue, usize),
Seq(usize),
Map,
}
/// Index of assertions and [`Observe`rs][crate::schemas::dataspace::Observe]. /// Index of assertions and [`Observe`rs][crate::schemas::dataspace::Observe].
/// ///
/// Generally speaking, you will not need to use this structure; /// Generally speaking, you will not need to use this structure;
@ -44,13 +37,13 @@ pub struct Index {
#[derive(Debug)] #[derive(Debug)]
struct Node { struct Node {
continuation: Continuation, continuation: Continuation,
edges: Map<Selector, Map<Guard, Node>>, edges: Map<Selector, Map<ds::GroupType, Node>>,
} }
#[derive(Debug)] #[derive(Debug)]
struct Continuation { struct Continuation {
cached_assertions: Set<AnyValue>, cached_assertions: Set<AnyValue>,
leaf_map: Map<Paths, Map<Captures, Leaf>>, leaf_map: Map<Arc<ConstantPositions>, Map<Captures, Leaf>>,
} }
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
@ -205,7 +198,7 @@ impl Node {
} }
fn extend(&mut self, pat: &ds::Pattern) -> &mut Continuation { fn extend(&mut self, pat: &ds::Pattern) -> &mut Continuation {
let (_pop_count, final_node) = self.extend_walk(&mut Vec::new(), 0, PathStep::Index(0), pat); let (_pop_count, final_node) = self.extend_walk(&mut Vec::new(), 0, PathStep::new(0), pat);
&mut final_node.continuation &mut final_node.continuation
} }
@ -216,23 +209,13 @@ impl Node {
step: PathStep, step: PathStep,
pat: &ds::Pattern, pat: &ds::Pattern,
) -> (usize, &mut Node) { ) -> (usize, &mut Node) {
let (guard, members): (Guard, Vec<(PathStep, &ds::Pattern)>) = match pat { let (guard, members): (ds::GroupType, Vec<(PathStep, &ds::Pattern)>) = match pat {
ds::Pattern::DCompound(b) => match &**b { ds::Pattern::Group { type_, entries } =>
ds::DCompound::Arr { items } => ((&**type_).clone(),
(Guard::Seq(items.len()), entries.iter().map(|(k, p)| (k.clone(), p)).collect()),
items.iter().enumerate().map(|(i, p)| (PathStep::Index(i), p)).collect()), ds::Pattern::Bind { pattern } =>
ds::DCompound::Rec { label, fields } => return self.extend_walk(path, pop_count, step, &**pattern),
(Guard::Rec(label.clone(), fields.len()), ds::Pattern::Discard | ds::Pattern::Lit { .. } =>
fields.iter().enumerate().map(|(i, p)| (PathStep::Index(i), p)).collect()),
ds::DCompound::Dict { entries, .. } =>
(Guard::Map,
entries.iter().map(|(k, p)| (PathStep::Key(k.clone()), p)).collect()),
}
ds::Pattern::DBind(b) => {
let ds::DBind { pattern, .. } = &**b;
return self.extend_walk(path, pop_count, step, pattern);
}
ds::Pattern::DDiscard(_) | ds::Pattern::DLit(_) =>
return (pop_count, self), return (pop_count, self),
}; };
@ -336,41 +319,46 @@ where FCont: FnMut(&mut Continuation, &AnyValue) -> (),
fn continuation(&mut self, c: &mut Continuation) { fn continuation(&mut self, c: &mut Continuation) {
(self.m_cont)(c, self.outer_value); (self.m_cont)(c, self.outer_value);
let mut empty_const_paths = Vec::new(); let mut empty_const_positions = Vec::new();
for (const_paths, const_val_map) in &mut c.leaf_map { for (const_positions, const_val_map) in &mut c.leaf_map {
if let Some(const_vals) = project_paths(self.outer_value, const_paths) { if project_paths(self.outer_value, &const_positions.required_to_exist).is_none() {
let leaf_opt = if self.create_leaf_if_absent { continue;
Some(const_val_map.entry(const_vals.clone()).or_insert_with(Leaf::new)) }
} else { let const_vals = match project_paths(self.outer_value, &const_positions.with_values) {
const_val_map.get_mut(&const_vals) Some(vs) => vs,
}; None => continue,
if let Some(leaf) = leaf_opt { };
(self.m_leaf)(leaf, self.outer_value); let leaf_opt = if self.create_leaf_if_absent {
for (capture_paths, endpoints) in &mut leaf.endpoints_map { Some(const_val_map.entry(const_vals.clone()).or_insert_with(Leaf::new))
if let Some(cs) = project_paths(self.outer_value, &capture_paths) { } else {
(self.m_endpoints)(endpoints, cs); const_val_map.get_mut(&const_vals)
} };
if let Some(leaf) = leaf_opt {
(self.m_leaf)(leaf, self.outer_value);
for (capture_paths, endpoints) in &mut leaf.endpoints_map {
if let Some(cs) = project_paths(self.outer_value, &capture_paths) {
(self.m_endpoints)(endpoints, cs);
} }
if leaf.is_empty() { }
const_val_map.remove(&const_vals); if leaf.is_empty() {
if const_val_map.is_empty() { const_val_map.remove(&const_vals);
empty_const_paths.push(const_paths.clone()); if const_val_map.is_empty() {
} empty_const_positions.push(const_positions.clone());
} }
} }
} }
} }
for const_paths in empty_const_paths { for const_positions in empty_const_positions {
c.leaf_map.remove(&const_paths); c.leaf_map.remove(&const_positions);
} }
} }
} }
fn class_of(v: &AnyValue) -> Option<Guard> { fn class_of(v: &AnyValue) -> Option<ds::GroupType> {
match v.value() { match v.value() {
Value::Sequence(vs) => Some(Guard::Seq(vs.len())), Value::Sequence(_) => Some(ds::GroupType::Arr),
Value::Record(r) => Some(Guard::Rec(r.label().clone(), r.arity())), Value::Record(r) => Some(ds::GroupType::Rec { label: r.label().clone() }),
Value::Dictionary(_) => Some(Guard::Map), Value::Dictionary(_) => Some(ds::GroupType::Dict),
_ => None, _ => None,
} }
} }
@ -398,15 +386,17 @@ fn project_paths<'a>(v: &'a AnyValue, ps: &Paths) -> Option<Captures> {
} }
fn step<'a>(v: &'a AnyValue, s: &PathStep) -> Option<&'a AnyValue> { fn step<'a>(v: &'a AnyValue, s: &PathStep) -> Option<&'a AnyValue> {
match (v.value(), s) { match v.value() {
(Value::Sequence(vs), PathStep::Index(i)) => Value::Sequence(vs) => {
if *i < vs.len() { Some(&vs[*i]) } else { None }, let i = s.value().as_usize()?;
(Value::Record(r), PathStep::Index(i)) => if i < vs.len() { Some(&vs[i]) } else { None }
if *i < r.arity() { Some(&r.fields()[*i]) } else { None }, }
(Value::Dictionary(m), PathStep::Key(k)) => Value::Record(r) => {
m.get(k), let i = s.value().as_usize()?;
_ => if i < r.arity() { Some(&r.fields()[i]) } else { None }
None, }
Value::Dictionary(m) => m.get(s),
_ => None,
} }
} }
@ -423,11 +413,14 @@ impl Continuation {
) { ) {
let cached_assertions = &self.cached_assertions; let cached_assertions = &self.cached_assertions;
let const_val_map = let const_val_map =
self.leaf_map.entry(analysis.const_paths.clone()).or_insert_with({ self.leaf_map.entry(analysis.const_positions.clone()).or_insert_with({
|| { || {
let mut cvm = Map::new(); let mut cvm = Map::new();
for a in cached_assertions { for a in cached_assertions {
if let Some(key) = project_paths(a, &analysis.const_paths) { if project_paths(a, &analysis.const_positions.required_to_exist).is_none() {
continue;
}
if let Some(key) = project_paths(a, &analysis.const_positions.with_values) {
cvm.entry(key).or_insert_with(Leaf::new) cvm.entry(key).or_insert_with(Leaf::new)
.cached_assertions.insert(a.clone()); .cached_assertions.insert(a.clone());
} }
@ -462,7 +455,7 @@ impl Continuation {
observer: &Arc<Cap>, observer: &Arc<Cap>,
) { ) {
if let Entry::Occupied(mut const_val_map_entry) if let Entry::Occupied(mut const_val_map_entry)
= self.leaf_map.entry(analysis.const_paths) = self.leaf_map.entry(analysis.const_positions)
{ {
let const_val_map = const_val_map_entry.get_mut(); let const_val_map = const_val_map_entry.get_mut();
if let Entry::Occupied(mut leaf_entry) if let Entry::Occupied(mut leaf_entry)