Abandoned path. Senders can only be moved oncde.
This commit is contained in:
parent
d824220fab
commit
c9de11ff61
159
Cargo.lock
generated
159
Cargo.lock
generated
@ -69,9 +69,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.85"
|
version = "0.1.87"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056"
|
checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -186,9 +186,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.8.0"
|
version = "2.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
@ -207,9 +207,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.9.0"
|
version = "1.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
|
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@ -219,9 +219,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.27"
|
version = "4.5.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796"
|
checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
@ -229,9 +229,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.5.27"
|
version = "4.5.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7"
|
checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
@ -241,9 +241,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "4.5.24"
|
version = "4.5.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c"
|
checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@ -399,7 +399,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi 0.13.3+wasi-0.2.2",
|
||||||
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -459,9 +471,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httparse"
|
name = "httparse"
|
||||||
version = "1.9.5"
|
version = "1.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
|
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httpdate"
|
name = "httpdate"
|
||||||
@ -471,9 +483,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "1.5.2"
|
version = "1.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0"
|
checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
@ -512,15 +524,15 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.14"
|
version = "1.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.169"
|
version = "0.2.170"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
@ -534,9 +546,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.25"
|
version = "0.4.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
|
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matchit"
|
name = "matchit"
|
||||||
@ -558,9 +570,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.8.3"
|
version = "0.8.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924"
|
checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"adler2",
|
"adler2",
|
||||||
]
|
]
|
||||||
@ -572,7 +584,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -585,6 +597,7 @@ dependencies = [
|
|||||||
"clap",
|
"clap",
|
||||||
"rand",
|
"rand",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tower",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -622,9 +635,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.20.2"
|
version = "1.20.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
@ -684,18 +697,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.93"
|
version = "1.0.94"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.38"
|
version = "1.0.39"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@ -727,14 +740,14 @@ 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",
|
"getrandom 0.2.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.5.8"
|
version = "0.5.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
|
checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
@ -747,15 +760,15 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.19"
|
version = "1.0.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
|
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.18"
|
version = "1.0.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
@ -765,18 +778,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.217"
|
version = "1.0.218"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
|
checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.217"
|
version = "1.0.218"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -785,9 +798,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.137"
|
version = "1.0.140"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b"
|
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"memchr",
|
"memchr",
|
||||||
@ -797,9 +810,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_path_to_error"
|
name = "serde_path_to_error"
|
||||||
version = "0.1.16"
|
version = "0.1.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6"
|
checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"serde",
|
"serde",
|
||||||
@ -839,9 +852,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.13.2"
|
version = "1.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
@ -873,9 +886,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.96"
|
version = "2.0.99"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
|
checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -890,9 +903,9 @@ checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.37"
|
version = "0.3.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
|
checksum = "bb041120f25f8fbe8fd2dbe4671c7c2ed74d83be2e7a77529bf7e0790ae3f472"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deranged",
|
"deranged",
|
||||||
"itoa",
|
"itoa",
|
||||||
@ -905,15 +918,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time-core"
|
name = "time-core"
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time-macros"
|
name = "time-macros"
|
||||||
version = "0.2.19"
|
version = "0.2.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
|
checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-conv",
|
"num-conv",
|
||||||
"time-core",
|
"time-core",
|
||||||
@ -998,15 +1011,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.17.0"
|
version = "1.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.15"
|
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 = "11cd88e12b17c6494200a9c1b683a04fcac9573ed74cd1b62aeb2727c5592243"
|
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
@ -1016,11 +1029,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.12.1"
|
version = "1.15.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b"
|
checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom 0.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1035,6 +1048,15 @@ version = "0.11.0+wasi-snapshot-preview1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.13.3+wasi-0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen-rt",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
@ -1117,6 +1139,15 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rt"
|
||||||
|
version = "0.33.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.7.35"
|
version = "0.7.35"
|
||||||
|
@ -12,3 +12,6 @@ clap = { version = "4.5.1", features = ["derive"] }
|
|||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
tokio = { version = "1.36.0", features = ["full"] }
|
tokio = { version = "1.36.0", features = ["full"] }
|
||||||
uuid = { version = "1.8.0", features = ["v4"] }
|
uuid = { version = "1.8.0", features = ["v4"] }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tower = { version = "0.5.2", features = ["util"] }
|
||||||
|
@ -4,6 +4,12 @@ use std::{
|
|||||||
thread::spawn,
|
thread::spawn,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum BackEndMessage {
|
||||||
|
Get,
|
||||||
|
Response(String),
|
||||||
|
}
|
||||||
|
|
||||||
struct BackEnd {
|
struct BackEnd {
|
||||||
tx: Sender<Message>,
|
tx: Sender<Message>,
|
||||||
rx: Receiver<Message>,
|
rx: Receiver<Message>,
|
||||||
@ -11,10 +17,7 @@ struct BackEnd {
|
|||||||
|
|
||||||
impl BackEnd {
|
impl BackEnd {
|
||||||
fn new(tx: Sender<Message>, rx: Receiver<Message>) -> Self {
|
fn new(tx: Sender<Message>, rx: Receiver<Message>) -> Self {
|
||||||
Self {
|
Self { tx: tx, rx: rx }
|
||||||
tx: tx,
|
|
||||||
rx: rx,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start(queue_tx: Sender<Message>) {
|
fn start(queue_tx: Sender<Message>) {
|
||||||
@ -29,22 +32,49 @@ impl BackEnd {
|
|||||||
fn listen(&self) {
|
fn listen(&self) {
|
||||||
loop {
|
loop {
|
||||||
self.rx.recv().unwrap();
|
self.rx.recv().unwrap();
|
||||||
|
self.tx
|
||||||
|
.send(BackEndMessage::Response("Something goes here".to_string()).into())
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod backends {
|
mod backends {
|
||||||
use std::time::Duration;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
fn run_service() -> (Sender<Message>, Receiver<Message>) {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
let service_tx: Sender<Message>;
|
||||||
|
BackEnd::start(tx);
|
||||||
|
match rx.recv().unwrap() {
|
||||||
|
Message::Register(result) => service_tx = result,
|
||||||
|
_ => unreachable!("should register the service"),
|
||||||
|
}
|
||||||
|
(service_tx, rx)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_registered() {
|
fn get_registered() {
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
BackEnd::start(tx);
|
BackEnd::start(tx);
|
||||||
match rx.recv_timeout(Duration::from_millis(500)).unwrap() {
|
match rx.recv_timeout(Duration::from_millis(500)).unwrap() {
|
||||||
Message::Register(_) => {},
|
Message::Register(_) => {}
|
||||||
_ => unreachable!("should register the service"),
|
_ => unreachable!("should register the service"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn request_home_page() {
|
||||||
|
let (tx, rx) = run_service();
|
||||||
|
tx.send(BackEndMessage::Get.into()).unwrap();
|
||||||
|
match rx.recv_timeout(Duration::from_millis(500)).unwrap() {
|
||||||
|
Message::BEMsg(result) => match result {
|
||||||
|
BackEndMessage::Response(_) => {}
|
||||||
|
_ => unreachable!("wrong message type"),
|
||||||
|
},
|
||||||
|
_ => unreachable!("wrong message type"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,91 @@
|
|||||||
|
use crate::{
|
||||||
|
queue::{Message, MessageData},
|
||||||
|
ClientMessage,
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
sync::mpsc::{channel, Receiver, Sender},
|
||||||
|
thread::spawn,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Reply;
|
||||||
|
|
||||||
|
impl Reply {
|
||||||
|
pub fn get_session(&self) -> String {
|
||||||
|
"id".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_content(&self) -> String {
|
||||||
|
"Something goes here.".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Client {
|
||||||
|
tx: Sender<Message>,
|
||||||
|
rx: Receiver<Message>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Client {
|
||||||
|
fn new(tx: Sender<Message>, rx: Receiver<Message>) -> Self {
|
||||||
|
Self {
|
||||||
|
tx: tx,
|
||||||
|
rx: rx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start(queue_tx: Sender<Message>) {
|
||||||
|
spawn(move || {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
let service = Self::new(queue_tx.clone(), rx);
|
||||||
|
queue_tx.send(Message::new(tx.into())).unwrap();
|
||||||
|
service.listen();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn listen(&self) {
|
||||||
|
loop {
|
||||||
|
let msg = self.rx.recv().unwrap();
|
||||||
|
match msg.get_data() {
|
||||||
|
MessageData::ClientMsg(output) => {
|
||||||
|
match output {
|
||||||
|
ClientMessage::Req(data) => {
|
||||||
|
let result = crate::client::Reply {};
|
||||||
|
data.tx.send(result).unwrap();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod clients {
|
||||||
|
use crate::create_requests::root_doc_no_sess;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn setup_client() -> (Sender<Message>, Receiver<Message>) {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
Client::start(tx);
|
||||||
|
let client_tx = match rx.recv().unwrap().get_data() {
|
||||||
|
MessageData::Register(result) => result.clone(),
|
||||||
|
_ => unreachable!("Register service first"),
|
||||||
|
};
|
||||||
|
(client_tx, rx)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_root_doc_request() {
|
||||||
|
let (tx, rx) = setup_client();
|
||||||
|
let (req, client_rx) = root_doc_no_sess();
|
||||||
|
tx.send(Message::new(req.into())).unwrap();
|
||||||
|
client_rx.recv().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
use super::{Message, Msg, MsgData, SessionMsg};
|
use super::{Message, Msg, MsgData, SessionMsg};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
@ -155,3 +243,4 @@ mod messages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
135
src/docbuilder.rs
Normal file
135
src/docbuilder.rs
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
use crate::{
|
||||||
|
field::Field,
|
||||||
|
queue::{Message, QueueClient},
|
||||||
|
};
|
||||||
|
use std::sync::mpsc::{Receiver, Sender};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Document {
|
||||||
|
session: Field,
|
||||||
|
content: Field,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Document {
|
||||||
|
pub fn new(session: Field, content: Field) -> Self {
|
||||||
|
Self {
|
||||||
|
session: session,
|
||||||
|
content: content,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the session id information.
|
||||||
|
pub fn get_session(&self) -> String {
|
||||||
|
self.session.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the requested content.
|
||||||
|
pub fn get_content(&self) -> String {
|
||||||
|
self.content.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod documeents {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_response() {
|
||||||
|
let id = "something";
|
||||||
|
let txt = "stuff";
|
||||||
|
let res = Document::new(id.into(), txt.into());
|
||||||
|
match res.session {
|
||||||
|
Field::Static(data) => assert_eq!(data, id),
|
||||||
|
_ => unreachable!("wrong field type"),
|
||||||
|
}
|
||||||
|
match res.content {
|
||||||
|
Field::Static(data) => assert_eq!(data, txt),
|
||||||
|
_ => unreachable!("wrong field type"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_id_string() {
|
||||||
|
let id = "id";
|
||||||
|
let doc = "content";
|
||||||
|
let reply = Document::new(id.into(), doc.into());
|
||||||
|
assert_eq!(reply.get_session(), id);
|
||||||
|
assert_eq!(reply.get_content(), doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_id_content() {
|
||||||
|
let id = "session";
|
||||||
|
let doc = "stuff";
|
||||||
|
let reply = Document::new(id.into(), doc.into());
|
||||||
|
assert_eq!(reply.get_session(), id);
|
||||||
|
assert_eq!(reply.get_content(), doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DocumentBuilder {
|
||||||
|
_tx: Sender<Message>,
|
||||||
|
rx: Receiver<Message>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QueueClient for DocumentBuilder {
|
||||||
|
fn new(tx: Sender<Message>, rx: Receiver<Message>) -> Self {
|
||||||
|
Self {
|
||||||
|
_tx: tx,
|
||||||
|
rx: rx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_receiver(&self) -> &Receiver<Message> {
|
||||||
|
&self.rx
|
||||||
|
}
|
||||||
|
|
||||||
|
fn listen(&self) {
|
||||||
|
let rx = self.get_receiver();
|
||||||
|
loop {
|
||||||
|
match rx.recv().unwrap() {
|
||||||
|
Message::Req(data) => {
|
||||||
|
//data.get_sender().send(Document::new("id".into(), "stuff".into())).unwrap();
|
||||||
|
let doc = Document::new("id".into(), "stuff".into());
|
||||||
|
data.send(doc);
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod builders {
|
||||||
|
use crate::request_test_data::request_root_document;
|
||||||
|
use std::sync::mpsc::{channel, TryRecvError};
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn run_service() -> (Sender<Message>, Receiver<Message>) {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
let service_tx: Sender<Message>;
|
||||||
|
DocumentBuilder::start(tx);
|
||||||
|
match rx.recv().unwrap() {
|
||||||
|
Message::Register(result) => service_tx = result,
|
||||||
|
_ => unreachable!("should register the service"),
|
||||||
|
}
|
||||||
|
(service_tx, rx)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_document() {
|
||||||
|
let (tx, rx) = run_service();
|
||||||
|
let (msg, msg_rx) = request_root_document();
|
||||||
|
tx.send(msg.into()).unwrap();
|
||||||
|
match rx.try_recv() {
|
||||||
|
Ok(_) => unreachable!("nothing should go back to the queue"),
|
||||||
|
Err(err) => {
|
||||||
|
match err {
|
||||||
|
TryRecvError::Empty => {},
|
||||||
|
_ => unreachable!("channel should still be open"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
msg_rx.recv().unwrap();
|
||||||
|
}
|
||||||
|
}
|
122
src/field.rs
Normal file
122
src/field.rs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
use std::fmt;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Field {
|
||||||
|
Static(String),
|
||||||
|
Uuid(Uuid),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for Field {
|
||||||
|
fn from(value: String) -> Self {
|
||||||
|
match Uuid::try_from(value.as_str()) {
|
||||||
|
Ok(data) => return Field::Uuid(data),
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
Field::Static(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for Field {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
match Uuid::try_from(value) {
|
||||||
|
Ok(data) => return Field::Uuid(data),
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
Field::Static(value.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Uuid> for Field {
|
||||||
|
fn from(value: Uuid) -> Self {
|
||||||
|
Field::Uuid(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Field {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Field::Uuid(data) => write!(f, "{}", data),
|
||||||
|
Field::Static(data) => write!(f, "{}", data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod fields {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn string_to_field() {
|
||||||
|
let entries = ["test1".to_string(), "test2".to_string()];
|
||||||
|
for data in entries {
|
||||||
|
match data.clone().into() {
|
||||||
|
Field::Static(result) => assert_eq!(result, data),
|
||||||
|
_ => unreachable!("shouuld have been a static field"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn str_to_field() {
|
||||||
|
let entries = ["test1", "test2"];
|
||||||
|
for data in entries {
|
||||||
|
match data.into() {
|
||||||
|
Field::Static(result) => assert_eq!(result, data),
|
||||||
|
_ => unreachable!("shouuld have been a static field"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn uuid_to_field() {
|
||||||
|
let id = Uuid::new_v4();
|
||||||
|
match id.into() {
|
||||||
|
Field::Uuid(result) => assert_eq!(result, id),
|
||||||
|
_ => unreachable!("should have been a uuid field"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn uuid_string_to_field() {
|
||||||
|
let id = Uuid::new_v4();
|
||||||
|
let id_string = id.to_string();
|
||||||
|
match id_string.into() {
|
||||||
|
Field::Uuid(result) => assert_eq!(result, id),
|
||||||
|
_ => unreachable!("should have been a uuid field"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn uuid_str_to_field() {
|
||||||
|
let id = Uuid::new_v4();
|
||||||
|
let id_string = id.to_string();
|
||||||
|
let id_str = id_string.as_str();
|
||||||
|
match id_str.into() {
|
||||||
|
Field::Uuid(result) => assert_eq!(result, id),
|
||||||
|
_ => unreachable!("should have been a uuid field"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn uuid_field_to_string() {
|
||||||
|
let id = Uuid::new_v4();
|
||||||
|
let result = id.to_string();
|
||||||
|
let input = Field::Uuid(id);
|
||||||
|
assert_eq!(input.to_string(), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn str_field_to_string() {
|
||||||
|
let result = "Something goes here";
|
||||||
|
let input: Field = result.into();
|
||||||
|
assert_eq!(input.to_string(), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn string_field_to_string() {
|
||||||
|
let result = "Another string".to_string();
|
||||||
|
let input: Field = result.clone().into();
|
||||||
|
assert_eq!(input.to_string(), result);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{queue::Message, session2::SessionMessage, Field, Request};
|
use crate::{backend::BackEndMessage, queue::Message, session2::SessionMessage, Field, Request};
|
||||||
use std::{
|
use std::{
|
||||||
sync::mpsc::{channel, Receiver, Sender},
|
sync::mpsc::{channel, Receiver, Sender},
|
||||||
thread::spawn,
|
thread::spawn,
|
||||||
@ -25,12 +25,31 @@ impl FrontEnd {
|
|||||||
|
|
||||||
fn listen(&self) {
|
fn listen(&self) {
|
||||||
loop {
|
loop {
|
||||||
self.rx.recv().unwrap();
|
match self.rx.recv().unwrap() {
|
||||||
|
Message::Req(output) => self.validate_session(output),
|
||||||
|
Message::SessMsg(output) => match output {
|
||||||
|
SessionMessage::New(data) => {
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
let id: Option<Field> = None;
|
let id: Option<Field> = None;
|
||||||
let msg: SessionMessage = id.into();
|
let msg: SessionMessage = id.into();
|
||||||
self.tx.send(msg.into()).unwrap();
|
self.tx.send(msg.into()).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn forward_request(&self, sess_id: Field) {
|
||||||
|
self.tx.send(BackEndMessage::Get.into()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_session(&self, req: Request) {
|
||||||
|
let id: Option<Field> = None;
|
||||||
|
let msg: SessionMessage = id.into();
|
||||||
|
self.tx.send(msg.into()).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -76,6 +95,12 @@ mod frontends {
|
|||||||
}
|
}
|
||||||
let (new_sess, sess_id) = create_session_new();
|
let (new_sess, sess_id) = create_session_new();
|
||||||
tx.send(new_sess.into()).unwrap();
|
tx.send(new_sess.into()).unwrap();
|
||||||
// generate backend request.
|
match rx.recv_timeout(Duration::from_millis(500)).unwrap() {
|
||||||
|
Message::BEMsg(result) => match result {
|
||||||
|
BackEndMessage::Get => {}
|
||||||
|
_ => unreachable!("incorrect message type"),
|
||||||
|
},
|
||||||
|
_ => unreachable!("incorrect message type"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
571
src/lib.rs
571
src/lib.rs
@ -1,572 +1,31 @@
|
|||||||
mod backend;
|
mod field;
|
||||||
mod client;
|
|
||||||
mod data;
|
|
||||||
mod error;
|
|
||||||
mod frontend;
|
|
||||||
mod message;
|
|
||||||
mod queue;
|
|
||||||
mod router;
|
|
||||||
mod session;
|
|
||||||
mod session2;
|
|
||||||
|
|
||||||
use client::{Client, ClientMsg};
|
use field::Field;
|
||||||
use message::{Message, MsgData};
|
|
||||||
use router::Router;
|
|
||||||
use session::{Session, SessionData, SessionMsg};
|
|
||||||
use std::{
|
|
||||||
collections::HashMap,
|
|
||||||
ops::Deref,
|
|
||||||
sync::mpsc::{channel, Receiver, Sender},
|
|
||||||
};
|
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
pub struct Reply;
|
||||||
enum Field {
|
|
||||||
Static(String),
|
|
||||||
Uuid(Uuid),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<String> for Field {
|
impl Reply {
|
||||||
fn from(value: String) -> Self {
|
pub fn get_session(&self) -> String {
|
||||||
match Uuid::try_from(value.as_str()) {
|
"id".to_string()
|
||||||
Ok(data) => return Field::Uuid(data),
|
|
||||||
Err(_) => {}
|
|
||||||
}
|
|
||||||
Field::Static(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&str> for Field {
|
|
||||||
fn from(value: &str) -> Self {
|
|
||||||
match Uuid::try_from(value) {
|
|
||||||
Ok(data) => return Field::Uuid(data),
|
|
||||||
Err(_) => {}
|
|
||||||
}
|
|
||||||
Field::Static(value.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Uuid> for Field {
|
|
||||||
fn from(value: Uuid) -> Self {
|
|
||||||
Field::Uuid(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod fields {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn string_to_field() {
|
|
||||||
let entries = ["test1".to_string(), "test2".to_string()];
|
|
||||||
for data in entries {
|
|
||||||
match data.clone().into() {
|
|
||||||
Field::Static(result) => assert_eq!(result, data),
|
|
||||||
_ => unreachable!("shouuld have been a static field"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
pub fn get_content(&self) -> String {
|
||||||
fn str_to_field() {
|
"Something goes here.".to_string()
|
||||||
let entries = ["test1", "test2"];
|
|
||||||
for data in entries {
|
|
||||||
match data.into() {
|
|
||||||
Field::Static(result) => assert_eq!(result, data),
|
|
||||||
_ => unreachable!("shouuld have been a static field"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn uuid_to_field() {
|
|
||||||
let id = Uuid::new_v4();
|
|
||||||
match id.into() {
|
|
||||||
Field::Uuid(result) => assert_eq!(result, id),
|
|
||||||
_ => unreachable!("should have been a uuid field"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn uuid_string_to_field() {
|
|
||||||
let id = Uuid::new_v4();
|
|
||||||
let id_string = id.to_string();
|
|
||||||
match id_string.into() {
|
|
||||||
Field::Uuid(result) => assert_eq!(result, id),
|
|
||||||
_ => unreachable!("should have been a uuid field"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn uuid_str_to_field() {
|
|
||||||
let id = Uuid::new_v4();
|
|
||||||
let id_string = id.to_string();
|
|
||||||
let id_str = id_string.as_str();
|
|
||||||
match id_str.into() {
|
|
||||||
Field::Uuid(result) => assert_eq!(result, id),
|
|
||||||
_ => unreachable!("should have been a uuid field"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Request {
|
pub struct MoreThanText;
|
||||||
id: Option<Field>,
|
|
||||||
tx: Sender<Response>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Request {
|
|
||||||
fn new<F>(id: Option<F>) -> (Self, Receiver<Response>)
|
|
||||||
where
|
|
||||||
F: Into<Field>,
|
|
||||||
{
|
|
||||||
let result: Option<Field>;
|
|
||||||
match id {
|
|
||||||
Some(data) => {
|
|
||||||
result = Some(data.into());
|
|
||||||
}
|
|
||||||
None => result = None,
|
|
||||||
}
|
|
||||||
let (tx, rx) = channel();
|
|
||||||
(Self { id: result, tx: tx }, rx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_session(&self) -> &Option<Field> {
|
|
||||||
return &self.id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod create_request {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
pub fn empty_request() -> (Request, Receiver<Response>) {
|
|
||||||
let id: Option<String> = None;
|
|
||||||
Request::new(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod requests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn create_request_no_id() {
|
|
||||||
let input: Option<String> = None;
|
|
||||||
let (req, _) = Request::new(input);
|
|
||||||
assert!(req.id.is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn create_request_with_uuid() {
|
|
||||||
let id = Uuid::new_v4();
|
|
||||||
let (req, _) = Request::new(Some(id));
|
|
||||||
match req.id {
|
|
||||||
Some(field) => match (field) {
|
|
||||||
Field::Uuid(data) => assert_eq!(data, id),
|
|
||||||
_ => unreachable!("Should have been a uuid"),
|
|
||||||
},
|
|
||||||
None => unreachable!("Should producer data"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn return_session() {
|
|
||||||
let id = Uuid::new_v4();
|
|
||||||
let (req, _) = Request::new(Some(id));
|
|
||||||
match req.get_session() {
|
|
||||||
Some(result) => {
|
|
||||||
match result {
|
|
||||||
Field::Uuid(data) => assert_eq!(data, &id),
|
|
||||||
_ => unreachable!("should have returned a uuid field"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
None => unreachable!("should have returned a uuid"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Record {
|
|
||||||
data: HashMap<String, Field>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Record {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
data: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add<S, F>(&mut self, name: S, data: F)
|
|
||||||
where
|
|
||||||
S: Into<String>,
|
|
||||||
F: Into<Field>,
|
|
||||||
{
|
|
||||||
self.data.insert(name.into(), data.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for Record {
|
|
||||||
type Target = HashMap<String, Field>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod records {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn initialize() {
|
|
||||||
let rec = Record::new();
|
|
||||||
assert!(rec.is_empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn bad_get_return() {
|
|
||||||
let rec = Record::new();
|
|
||||||
match rec.get("empty") {
|
|
||||||
Some(_) => unreachable!("Should_have returned a None"),
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn add_data() {
|
|
||||||
let name = "name1x";
|
|
||||||
let data = "data1";
|
|
||||||
let mut rec = Record::new();
|
|
||||||
rec.add(name, data);
|
|
||||||
match rec.get(name) {
|
|
||||||
None => unreachable!("Should return data"),
|
|
||||||
Some(result) => match result {
|
|
||||||
Field::Static(txt) => assert_eq!(txt, data),
|
|
||||||
_ => unreachable!("Should have been static"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn add_data_strings() {
|
|
||||||
let name = "field".to_string();
|
|
||||||
let data = "info".to_string();
|
|
||||||
let mut rec = Record::new();
|
|
||||||
rec.add(name.clone(), data.clone());
|
|
||||||
match rec.get(&name) {
|
|
||||||
None => unreachable!("Should return data"),
|
|
||||||
Some(result) => match result {
|
|
||||||
Field::Static(txt) => assert_eq!(txt, &data),
|
|
||||||
_ => unreachable!("should have been statis"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum ResponseError {
|
|
||||||
ColumnNumberMisMatch,
|
|
||||||
MissionColumn(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Response {
|
|
||||||
data: HashMap<String, Vec<Field>>,
|
|
||||||
counter: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Response {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
data: HashMap::new(),
|
|
||||||
counter: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add(&mut self, rec: Record) -> Result<(), ResponseError> {
|
|
||||||
if self.data.is_empty() {
|
|
||||||
for (key, value) in rec.iter() {
|
|
||||||
let mut store = Vec::new();
|
|
||||||
store.push(value.clone());
|
|
||||||
self.data.insert(key.to_string(), store);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if rec.len() != self.data.len() {
|
|
||||||
return Err(ResponseError::ColumnNumberMisMatch);
|
|
||||||
}
|
|
||||||
for (key, value) in rec.iter() {
|
|
||||||
match self.data.get_mut(key) {
|
|
||||||
Some(data) => data.push(value.clone()),
|
|
||||||
None => return Err(ResponseError::MissionColumn(key.to_string())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Iterator for Response {
|
|
||||||
type Item = Record;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
if self.data.is_empty() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let mut rec = Record::new();
|
|
||||||
for (key, value) in self.data.iter() {
|
|
||||||
if self.counter >= value.len() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
rec.add(key, value[self.counter].clone());
|
|
||||||
}
|
|
||||||
self.counter += 1;
|
|
||||||
Some(rec)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod responses {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn create_response() {
|
|
||||||
let mut res = Response::new();
|
|
||||||
assert!(res.data.is_empty());
|
|
||||||
assert!(res.next().is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn add_records() {
|
|
||||||
let mut res = Response::new();
|
|
||||||
let columns = ["col1", "col2"];
|
|
||||||
let count = 3;
|
|
||||||
let field_cnt = &count * columns.len();
|
|
||||||
let mut fields = 0..field_cnt;
|
|
||||||
for _ in 0..count {
|
|
||||||
let mut rec = Record::new();
|
|
||||||
for col in columns {
|
|
||||||
rec.add(col, fields.next().unwrap().to_string());
|
|
||||||
}
|
|
||||||
res.add(rec);
|
|
||||||
}
|
|
||||||
fields = 0..field_cnt;
|
|
||||||
for _ in 0..count {
|
|
||||||
match res.next() {
|
|
||||||
Some(rec) => {
|
|
||||||
assert_eq!(rec.len(), columns.len());
|
|
||||||
for col in columns {
|
|
||||||
match rec.get(col).unwrap() {
|
|
||||||
Field::Static(txt) => {
|
|
||||||
assert_eq!(txt.clone(), fields.next().unwrap().to_string())
|
|
||||||
}
|
|
||||||
_ => unreachable!("should have been static"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => unreachable!("Should have returned data"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert!(res.next().is_none(), "exceeded the correct of records");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn number_of_columns_mismatch() {
|
|
||||||
let mut res = Response::new();
|
|
||||||
let mut rec1 = Record::new();
|
|
||||||
let mut rec2 = Record::new();
|
|
||||||
rec1.add("one", "one");
|
|
||||||
rec2.add("one", "one");
|
|
||||||
rec2.add("two", "two");
|
|
||||||
res.add(rec1).unwrap();
|
|
||||||
match res.add(rec2) {
|
|
||||||
Ok(_) => unreachable!("Should not accept additional value"),
|
|
||||||
Err(err) => match err {
|
|
||||||
ResponseError::ColumnNumberMisMatch => {}
|
|
||||||
_ => unreachable!("should havee been a mismatch error"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn missing_field_error() {
|
|
||||||
let mut res = Response::new();
|
|
||||||
let mut rec1 = Record::new();
|
|
||||||
let mut rec2 = Record::new();
|
|
||||||
rec1.add("one", "one");
|
|
||||||
rec2.add("one", "one");
|
|
||||||
rec2.add("two", "two");
|
|
||||||
res.add(rec2).unwrap();
|
|
||||||
match res.add(rec1) {
|
|
||||||
Ok(_) => unreachable!("Should not accept additional value"),
|
|
||||||
Err(err) => match err {
|
|
||||||
ResponseError::ColumnNumberMisMatch => {}
|
|
||||||
_ => unreachable!("should havee been a mismatch error"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn wrong_column_name() {
|
|
||||||
let mut res = Response::new();
|
|
||||||
let mut rec1 = Record::new();
|
|
||||||
let mut rec2 = Record::new();
|
|
||||||
rec1.add("one", "one");
|
|
||||||
rec2.add("two", "two");
|
|
||||||
res.add(rec1).unwrap();
|
|
||||||
match res.add(rec2) {
|
|
||||||
Ok(_) => unreachable!("Should not accept additional value"),
|
|
||||||
Err(err) => match err {
|
|
||||||
ResponseError::MissionColumn(txt) => assert_eq!(txt, "two"),
|
|
||||||
_ => unreachable!("should have been missing cloumn"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Support functions for Messages.
|
|
||||||
pub trait Msg {
|
|
||||||
fn to_msgdata(&self) -> MsgData;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test_message {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
pub enum Tester {
|
|
||||||
Test1,
|
|
||||||
Test2,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Msg for Tester {
|
|
||||||
fn to_msgdata(&self) -> MsgData {
|
|
||||||
match self {
|
|
||||||
Tester::Test1 => MsgData::Test1,
|
|
||||||
Tester::Test2 => MsgData::Test2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Application client to MoreThanText
|
|
||||||
pub struct MoreThanText {
|
|
||||||
// tx: Sender<Message>,
|
|
||||||
session: Option<SessionData>,
|
|
||||||
tx: Sender<Message>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MoreThanText {
|
impl MoreThanText {
|
||||||
/// Create a MoreThanText database.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use morethantext::MoreThanText;
|
|
||||||
///
|
|
||||||
/// MoreThanText::new();
|
|
||||||
/// ```
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
/* Future code.
|
Self {}
|
||||||
* tx = Queue::start();
|
|
||||||
* tx.send(Session::start().into()).unwrap();
|
|
||||||
* Self { tx: tx }
|
|
||||||
*/
|
|
||||||
let (tx, rx) = channel();
|
|
||||||
let mut senders = Vec::new();
|
|
||||||
senders.push(Client::start(tx.clone()));
|
|
||||||
senders.push(Session::start(tx.clone()));
|
|
||||||
Router::start(senders, rx);
|
|
||||||
Self {
|
|
||||||
session: None,
|
|
||||||
tx: tx,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Opens an existing or new session with the database.
|
pub fn request<F>(&self, _session: Option<F>) -> Reply
|
||||||
///
|
where
|
||||||
/// If the string is None, incorrect, or expired,
|
F: Into<Field>,
|
||||||
/// a new session will be created.
|
{
|
||||||
///
|
Reply {}
|
||||||
/// Example:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use morethantext::MoreThanText;
|
|
||||||
///
|
|
||||||
/// let mut mtt = MoreThanText::new();
|
|
||||||
/// mtt.open_session(None);
|
|
||||||
/// mtt.open_session(Some("7b1ff340-7dfa-4f29-b144-601384e54423".to_string()));
|
|
||||||
/// ```
|
|
||||||
pub fn open_session(&mut self, id: Option<String>) {
|
|
||||||
let (tx, rx) = channel();
|
|
||||||
let req = ClientMsg::OpenSession(id, tx);
|
|
||||||
let msg = Message::new(&req);
|
|
||||||
self.tx.send(msg).unwrap();
|
|
||||||
match rx.recv().unwrap().get_message() {
|
|
||||||
MsgData::Session(data) => match data {
|
|
||||||
SessionMsg::Opened(sess) => self.session = Some(sess.clone()),
|
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the session id
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use morethantext::MoreThanText;
|
|
||||||
///
|
|
||||||
/// let mut mtt = MoreThanText::new();
|
|
||||||
/// let id = mtt.get_id();
|
|
||||||
/// ```
|
|
||||||
pub fn get_id(&self) -> String {
|
|
||||||
match &self.session {
|
|
||||||
Some(id) => id.to_string(),
|
|
||||||
None => "".to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for MoreThanText {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
Self {
|
|
||||||
session: None,
|
|
||||||
tx: self.tx.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod mtt_client {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn default_values() {
|
|
||||||
let mtt = MoreThanText::new();
|
|
||||||
assert!(mtt.session.is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn new_session() {
|
|
||||||
let mut mtt = MoreThanText::new();
|
|
||||||
mtt.open_session(None);
|
|
||||||
assert!(mtt.session.is_some());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn session_ids_are_unique() {
|
|
||||||
let mut mtt = MoreThanText::new();
|
|
||||||
mtt.open_session(None);
|
|
||||||
let id1 = mtt.get_id();
|
|
||||||
mtt.open_session(None);
|
|
||||||
assert_ne!(mtt.get_id(), id1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn cloned_clients_have_no_session() {
|
|
||||||
let mut mtt = MoreThanText::new();
|
|
||||||
mtt.open_session(None);
|
|
||||||
let result = mtt.clone();
|
|
||||||
assert!(result.session.is_none());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
77
src/main.rs
77
src/main.rs
@ -1,8 +1,8 @@
|
|||||||
use axum::{extract::State, response::IntoResponse, routing::get, Router};
|
use axum::{extract::State, handler::Handler, response::IntoResponse};
|
||||||
use axum_extra::extract::cookie::{Cookie, CookieJar};
|
use axum_extra::extract::cookie::{Cookie, CookieJar};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
//use morethantext::{MoreThanText, Session};
|
|
||||||
use morethantext::MoreThanText;
|
use morethantext::MoreThanText;
|
||||||
|
use tokio::{spawn, sync::mpsc::channel};
|
||||||
|
|
||||||
const LOCALHOST: &str = "127.0.0.1";
|
const LOCALHOST: &str = "127.0.0.1";
|
||||||
const SESSION_KEY: &str = "sessionid";
|
const SESSION_KEY: &str = "sessionid";
|
||||||
@ -21,28 +21,32 @@ struct Args {
|
|||||||
node: Vec<String>,
|
node: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod http_session {
|
|
||||||
#[tokio::test]
|
|
||||||
async fn my_test() {
|
|
||||||
assert!(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
let addr = format!("{}:{}", args.address, args.port);
|
let addr = format!("{}:{}", args.address, args.port);
|
||||||
let state = MoreThanText::new();
|
let state = MoreThanText::new();
|
||||||
let app = Router::new().route("/", get(handler)).with_state(state);
|
let app = mtt_conn.with_state(state);
|
||||||
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
||||||
axum::serve(listener, app.into_make_service())
|
axum::serve(listener, app.into_make_service())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handler(jar: CookieJar, mut state: State<MoreThanText>) -> impl IntoResponse {
|
async fn mtt_conn(jar: CookieJar, state: State<MoreThanText>) -> impl IntoResponse {
|
||||||
let mut cookies = jar.clone();
|
let sid = match jar.get(SESSION_KEY) {
|
||||||
|
Some(cookie) => Some(cookie.value().to_string()),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
let (tx, mut rx) = channel(5);
|
||||||
|
spawn(async move {
|
||||||
|
tx.send(state.request(sid)).await.unwrap();
|
||||||
|
});
|
||||||
|
let reply = rx.recv().await.unwrap();
|
||||||
|
let cookie = Cookie::build((SESSION_KEY, reply.get_session()));
|
||||||
|
let cookies = jar.add(cookie);
|
||||||
|
|
||||||
|
/*
|
||||||
let sid = match jar.get(SESSION_KEY) {
|
let sid = match jar.get(SESSION_KEY) {
|
||||||
Some(cookie) => Some(cookie.value().to_string()),
|
Some(cookie) => Some(cookie.value().to_string()),
|
||||||
None => None,
|
None => None,
|
||||||
@ -52,5 +56,50 @@ async fn handler(jar: CookieJar, mut state: State<MoreThanText>) -> impl IntoRes
|
|||||||
let cookie = Cookie::build((SESSION_KEY, state.get_id()));
|
let cookie = Cookie::build((SESSION_KEY, state.get_id()));
|
||||||
cookies = jar.add(cookie);
|
cookies = jar.add(cookie);
|
||||||
}
|
}
|
||||||
(cookies, "Something goes here.")
|
*/
|
||||||
|
(cookies, reply.get_content())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod servers {
|
||||||
|
use super::*;
|
||||||
|
use axum::{
|
||||||
|
body::Body,
|
||||||
|
http::{Request, StatusCode},
|
||||||
|
};
|
||||||
|
use tower::ServiceExt;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn get_home_page() {
|
||||||
|
let app = mtt_conn.with_state(MoreThanText::new());
|
||||||
|
let response = app
|
||||||
|
.oneshot(Request::builder().uri("/").body(Body::empty()).unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
let sessid = format!("{:?}", response.headers().get("set-cookie").unwrap());
|
||||||
|
assert!(sessid.contains(SESSION_KEY), "did not set session id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#[tokio::test]
|
||||||
|
async fn session_ids_are_unique() {
|
||||||
|
let app = mtt_conn.with_state(MoreThanText::new());
|
||||||
|
let mut holder: Vec<String> = Vec::new();
|
||||||
|
for _ in 0..5 {
|
||||||
|
let response = app
|
||||||
|
.clone()
|
||||||
|
.oneshot(Request::builder().uri("/").body(Body::empty()).unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let sessid = format!("{:?}", response.headers().get("set-cookie").unwrap());
|
||||||
|
assert!(
|
||||||
|
!holder.contains(&sessid),
|
||||||
|
"found duplicate entry: {:?}",
|
||||||
|
holder
|
||||||
|
);
|
||||||
|
holder.push(sessid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
597
src/old-lib.rs
Normal file
597
src/old-lib.rs
Normal file
@ -0,0 +1,597 @@
|
|||||||
|
mod backend;
|
||||||
|
mod client;
|
||||||
|
mod data;
|
||||||
|
mod error;
|
||||||
|
mod frontend;
|
||||||
|
mod message;
|
||||||
|
mod queue;
|
||||||
|
mod router;
|
||||||
|
mod session;
|
||||||
|
mod session2;
|
||||||
|
|
||||||
|
use client::{Client, ClientMsg};
|
||||||
|
use message::{Message, MsgData};
|
||||||
|
use router::Router;
|
||||||
|
use session::{Session, SessionData, SessionMsg};
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
ops::Deref,
|
||||||
|
sync::mpsc::{channel, Receiver, Sender},
|
||||||
|
thread::spawn,
|
||||||
|
};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is code to finish once sessions have been ransfered,
|
||||||
|
* and the dead code is removed.
|
||||||
|
*
|
||||||
|
trait MessageService: Sized {
|
||||||
|
fn new(tx: Sender<Message>, rx: Receiver<Message>) -> Self;
|
||||||
|
|
||||||
|
fn start(queue_tx: Sender<Message>) {
|
||||||
|
spawn(move || {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
let service = Self::new(queue_tx.clone(), rx);
|
||||||
|
queue_tx.send(tx.clone().into()).unwrap();
|
||||||
|
service.listen();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn listen(&self) {
|
||||||
|
loop {
|
||||||
|
self.rx.recv().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum Field {
|
||||||
|
Static(String),
|
||||||
|
Uuid(Uuid),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for Field {
|
||||||
|
fn from(value: String) -> Self {
|
||||||
|
match Uuid::try_from(value.as_str()) {
|
||||||
|
Ok(data) => return Field::Uuid(data),
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
Field::Static(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for Field {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
match Uuid::try_from(value) {
|
||||||
|
Ok(data) => return Field::Uuid(data),
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
Field::Static(value.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Uuid> for Field {
|
||||||
|
fn from(value: Uuid) -> Self {
|
||||||
|
Field::Uuid(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod fields {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn string_to_field() {
|
||||||
|
let entries = ["test1".to_string(), "test2".to_string()];
|
||||||
|
for data in entries {
|
||||||
|
match data.clone().into() {
|
||||||
|
Field::Static(result) => assert_eq!(result, data),
|
||||||
|
_ => unreachable!("shouuld have been a static field"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn str_to_field() {
|
||||||
|
let entries = ["test1", "test2"];
|
||||||
|
for data in entries {
|
||||||
|
match data.into() {
|
||||||
|
Field::Static(result) => assert_eq!(result, data),
|
||||||
|
_ => unreachable!("shouuld have been a static field"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn uuid_to_field() {
|
||||||
|
let id = Uuid::new_v4();
|
||||||
|
match id.into() {
|
||||||
|
Field::Uuid(result) => assert_eq!(result, id),
|
||||||
|
_ => unreachable!("should have been a uuid field"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn uuid_string_to_field() {
|
||||||
|
let id = Uuid::new_v4();
|
||||||
|
let id_string = id.to_string();
|
||||||
|
match id_string.into() {
|
||||||
|
Field::Uuid(result) => assert_eq!(result, id),
|
||||||
|
_ => unreachable!("should have been a uuid field"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn uuid_str_to_field() {
|
||||||
|
let id = Uuid::new_v4();
|
||||||
|
let id_string = id.to_string();
|
||||||
|
let id_str = id_string.as_str();
|
||||||
|
match id_str.into() {
|
||||||
|
Field::Uuid(result) => assert_eq!(result, id),
|
||||||
|
_ => unreachable!("should have been a uuid field"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Request {
|
||||||
|
id: Option<Field>,
|
||||||
|
tx: Sender<Response>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Request {
|
||||||
|
fn new<F>(id: Option<F>) -> (Self, Receiver<Response>)
|
||||||
|
where
|
||||||
|
F: Into<Field>,
|
||||||
|
{
|
||||||
|
let result: Option<Field>;
|
||||||
|
match id {
|
||||||
|
Some(data) => {
|
||||||
|
result = Some(data.into());
|
||||||
|
}
|
||||||
|
None => result = None,
|
||||||
|
}
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
(Self { id: result, tx: tx }, rx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_session(&self) -> &Option<Field> {
|
||||||
|
return &self.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod create_request {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub fn empty_request() -> (Request, Receiver<Response>) {
|
||||||
|
let id: Option<String> = None;
|
||||||
|
Request::new(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod requests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_request_no_id() {
|
||||||
|
let input: Option<String> = None;
|
||||||
|
let (req, _) = Request::new(input);
|
||||||
|
assert!(req.id.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_request_with_uuid() {
|
||||||
|
let id = Uuid::new_v4();
|
||||||
|
let (req, _) = Request::new(Some(id));
|
||||||
|
match req.id {
|
||||||
|
Some(field) => match (field) {
|
||||||
|
Field::Uuid(data) => assert_eq!(data, id),
|
||||||
|
_ => unreachable!("Should have been a uuid"),
|
||||||
|
},
|
||||||
|
None => unreachable!("Should producer data"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn return_session() {
|
||||||
|
let id = Uuid::new_v4();
|
||||||
|
let (req, _) = Request::new(Some(id));
|
||||||
|
match req.get_session() {
|
||||||
|
Some(result) => {
|
||||||
|
match result {
|
||||||
|
Field::Uuid(data) => assert_eq!(data, &id),
|
||||||
|
_ => unreachable!("should have returned a uuid field"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
None => unreachable!("should have returned a uuid"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Record {
|
||||||
|
data: HashMap<String, Field>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Record {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
data: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add<S, F>(&mut self, name: S, data: F)
|
||||||
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
F: Into<Field>,
|
||||||
|
{
|
||||||
|
self.data.insert(name.into(), data.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Record {
|
||||||
|
type Target = HashMap<String, Field>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod records {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn initialize() {
|
||||||
|
let rec = Record::new();
|
||||||
|
assert!(rec.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bad_get_return() {
|
||||||
|
let rec = Record::new();
|
||||||
|
match rec.get("empty") {
|
||||||
|
Some(_) => unreachable!("Should_have returned a None"),
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn add_data() {
|
||||||
|
let name = "name1x";
|
||||||
|
let data = "data1";
|
||||||
|
let mut rec = Record::new();
|
||||||
|
rec.add(name, data);
|
||||||
|
match rec.get(name) {
|
||||||
|
None => unreachable!("Should return data"),
|
||||||
|
Some(result) => match result {
|
||||||
|
Field::Static(txt) => assert_eq!(txt, data),
|
||||||
|
_ => unreachable!("Should have been static"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn add_data_strings() {
|
||||||
|
let name = "field".to_string();
|
||||||
|
let data = "info".to_string();
|
||||||
|
let mut rec = Record::new();
|
||||||
|
rec.add(name.clone(), data.clone());
|
||||||
|
match rec.get(&name) {
|
||||||
|
None => unreachable!("Should return data"),
|
||||||
|
Some(result) => match result {
|
||||||
|
Field::Static(txt) => assert_eq!(txt, &data),
|
||||||
|
_ => unreachable!("should have been statis"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum ResponseError {
|
||||||
|
ColumnNumberMisMatch,
|
||||||
|
MissionColumn(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Response {
|
||||||
|
data: HashMap<String, Vec<Field>>,
|
||||||
|
counter: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Response {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
data: HashMap::new(),
|
||||||
|
counter: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(&mut self, rec: Record) -> Result<(), ResponseError> {
|
||||||
|
if self.data.is_empty() {
|
||||||
|
for (key, value) in rec.iter() {
|
||||||
|
let mut store = Vec::new();
|
||||||
|
store.push(value.clone());
|
||||||
|
self.data.insert(key.to_string(), store);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if rec.len() != self.data.len() {
|
||||||
|
return Err(ResponseError::ColumnNumberMisMatch);
|
||||||
|
}
|
||||||
|
for (key, value) in rec.iter() {
|
||||||
|
match self.data.get_mut(key) {
|
||||||
|
Some(data) => data.push(value.clone()),
|
||||||
|
None => return Err(ResponseError::MissionColumn(key.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for Response {
|
||||||
|
type Item = Record;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.data.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut rec = Record::new();
|
||||||
|
for (key, value) in self.data.iter() {
|
||||||
|
if self.counter >= value.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
rec.add(key, value[self.counter].clone());
|
||||||
|
}
|
||||||
|
self.counter += 1;
|
||||||
|
Some(rec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod responses {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_response() {
|
||||||
|
let mut res = Response::new();
|
||||||
|
assert!(res.data.is_empty());
|
||||||
|
assert!(res.next().is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn add_records() {
|
||||||
|
let mut res = Response::new();
|
||||||
|
let columns = ["col1", "col2"];
|
||||||
|
let count = 3;
|
||||||
|
let field_cnt = &count * columns.len();
|
||||||
|
let mut fields = 0..field_cnt;
|
||||||
|
for _ in 0..count {
|
||||||
|
let mut rec = Record::new();
|
||||||
|
for col in columns {
|
||||||
|
rec.add(col, fields.next().unwrap().to_string());
|
||||||
|
}
|
||||||
|
res.add(rec);
|
||||||
|
}
|
||||||
|
fields = 0..field_cnt;
|
||||||
|
for _ in 0..count {
|
||||||
|
match res.next() {
|
||||||
|
Some(rec) => {
|
||||||
|
assert_eq!(rec.len(), columns.len());
|
||||||
|
for col in columns {
|
||||||
|
match rec.get(col).unwrap() {
|
||||||
|
Field::Static(txt) => {
|
||||||
|
assert_eq!(txt.clone(), fields.next().unwrap().to_string())
|
||||||
|
}
|
||||||
|
_ => unreachable!("should have been static"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => unreachable!("Should have returned data"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert!(res.next().is_none(), "exceeded the correct of records");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn number_of_columns_mismatch() {
|
||||||
|
let mut res = Response::new();
|
||||||
|
let mut rec1 = Record::new();
|
||||||
|
let mut rec2 = Record::new();
|
||||||
|
rec1.add("one", "one");
|
||||||
|
rec2.add("one", "one");
|
||||||
|
rec2.add("two", "two");
|
||||||
|
res.add(rec1).unwrap();
|
||||||
|
match res.add(rec2) {
|
||||||
|
Ok(_) => unreachable!("Should not accept additional value"),
|
||||||
|
Err(err) => match err {
|
||||||
|
ResponseError::ColumnNumberMisMatch => {}
|
||||||
|
_ => unreachable!("should havee been a mismatch error"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn missing_field_error() {
|
||||||
|
let mut res = Response::new();
|
||||||
|
let mut rec1 = Record::new();
|
||||||
|
let mut rec2 = Record::new();
|
||||||
|
rec1.add("one", "one");
|
||||||
|
rec2.add("one", "one");
|
||||||
|
rec2.add("two", "two");
|
||||||
|
res.add(rec2).unwrap();
|
||||||
|
match res.add(rec1) {
|
||||||
|
Ok(_) => unreachable!("Should not accept additional value"),
|
||||||
|
Err(err) => match err {
|
||||||
|
ResponseError::ColumnNumberMisMatch => {}
|
||||||
|
_ => unreachable!("should havee been a mismatch error"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn wrong_column_name() {
|
||||||
|
let mut res = Response::new();
|
||||||
|
let mut rec1 = Record::new();
|
||||||
|
let mut rec2 = Record::new();
|
||||||
|
rec1.add("one", "one");
|
||||||
|
rec2.add("two", "two");
|
||||||
|
res.add(rec1).unwrap();
|
||||||
|
match res.add(rec2) {
|
||||||
|
Ok(_) => unreachable!("Should not accept additional value"),
|
||||||
|
Err(err) => match err {
|
||||||
|
ResponseError::MissionColumn(txt) => assert_eq!(txt, "two"),
|
||||||
|
_ => unreachable!("should have been missing cloumn"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Support functions for Messages.
|
||||||
|
pub trait Msg {
|
||||||
|
fn to_msgdata(&self) -> MsgData;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test_message {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub enum Tester {
|
||||||
|
Test1,
|
||||||
|
Test2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Msg for Tester {
|
||||||
|
fn to_msgdata(&self) -> MsgData {
|
||||||
|
match self {
|
||||||
|
Tester::Test1 => MsgData::Test1,
|
||||||
|
Tester::Test2 => MsgData::Test2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Application client to MoreThanText
|
||||||
|
pub struct MoreThanText {
|
||||||
|
// tx: Sender<Message>,
|
||||||
|
session: Option<SessionData>,
|
||||||
|
tx: Sender<Message>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MoreThanText {
|
||||||
|
/// Create a MoreThanText database.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use morethantext::MoreThanText;
|
||||||
|
///
|
||||||
|
/// MoreThanText::new();
|
||||||
|
/// ```
|
||||||
|
pub fn new() -> Self {
|
||||||
|
/* Future code.
|
||||||
|
* tx = Queue::start();
|
||||||
|
* tx.send(Session::start().into()).unwrap();
|
||||||
|
* Self { tx: tx }
|
||||||
|
*/
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
let mut senders = Vec::new();
|
||||||
|
senders.push(Client::start(tx.clone()));
|
||||||
|
senders.push(Session::start(tx.clone()));
|
||||||
|
Router::start(senders, rx);
|
||||||
|
Self {
|
||||||
|
session: None,
|
||||||
|
tx: tx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Opens an existing or new session with the database.
|
||||||
|
///
|
||||||
|
/// If the string is None, incorrect, or expired,
|
||||||
|
/// a new session will be created.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use morethantext::MoreThanText;
|
||||||
|
///
|
||||||
|
/// let mut mtt = MoreThanText::new();
|
||||||
|
/// mtt.open_session(None);
|
||||||
|
/// mtt.open_session(Some("7b1ff340-7dfa-4f29-b144-601384e54423".to_string()));
|
||||||
|
/// ```
|
||||||
|
pub fn open_session(&mut self, id: Option<String>) {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
let req = ClientMsg::OpenSession(id, tx);
|
||||||
|
let msg = Message::new(&req);
|
||||||
|
self.tx.send(msg).unwrap();
|
||||||
|
match rx.recv().unwrap().get_message() {
|
||||||
|
MsgData::Session(data) => match data {
|
||||||
|
SessionMsg::Opened(sess) => self.session = Some(sess.clone()),
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the session id
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use morethantext::MoreThanText;
|
||||||
|
///
|
||||||
|
/// let mut mtt = MoreThanText::new();
|
||||||
|
/// let id = mtt.get_id();
|
||||||
|
/// ```
|
||||||
|
pub fn get_id(&self) -> String {
|
||||||
|
match &self.session {
|
||||||
|
Some(id) => id.to_string(),
|
||||||
|
None => "".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for MoreThanText {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
session: None,
|
||||||
|
tx: self.tx.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod mtt_client {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_values() {
|
||||||
|
let mtt = MoreThanText::new();
|
||||||
|
assert!(mtt.session.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_session() {
|
||||||
|
let mut mtt = MoreThanText::new();
|
||||||
|
mtt.open_session(None);
|
||||||
|
assert!(mtt.session.is_some());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn session_ids_are_unique() {
|
||||||
|
let mut mtt = MoreThanText::new();
|
||||||
|
mtt.open_session(None);
|
||||||
|
let id1 = mtt.get_id();
|
||||||
|
mtt.open_session(None);
|
||||||
|
assert_ne!(mtt.get_id(), id1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cloned_clients_have_no_session() {
|
||||||
|
let mut mtt = MoreThanText::new();
|
||||||
|
mtt.open_session(None);
|
||||||
|
let result = mtt.clone();
|
||||||
|
assert!(result.session.is_none());
|
||||||
|
}
|
||||||
|
}
|
156
src/old-queue.rs
Normal file
156
src/old-queue.rs
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
use crate::{backend::BackEndMessage, session2::SessionMessage, Request};
|
||||||
|
use std::{
|
||||||
|
sync::mpsc::{channel, Receiver, Sender},
|
||||||
|
thread::spawn,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum Message {
|
||||||
|
BEMsg(BackEndMessage),
|
||||||
|
Register(Sender<Message>),
|
||||||
|
Req(Request),
|
||||||
|
SessMsg(SessionMessage),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Request> for Message {
|
||||||
|
fn from(value: Request) -> Self {
|
||||||
|
Message::Req(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Sender<Message>> for Message {
|
||||||
|
fn from(value: Sender<Message>) -> Self {
|
||||||
|
Message::Register(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SessionMessage> for Message {
|
||||||
|
fn from(value: SessionMessage) -> Self {
|
||||||
|
Message::SessMsg(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BackEndMessage> for Message {
|
||||||
|
fn from(value: BackEndMessage) -> Self {
|
||||||
|
Message::BEMsg(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod messages {
|
||||||
|
use super::*;
|
||||||
|
use crate::{create_request::empty_request, Field};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_request() {
|
||||||
|
let (req, _) = empty_request();
|
||||||
|
match req.into() {
|
||||||
|
Message::Req(result) => assert!(result.get_session().is_none()),
|
||||||
|
_ => unreachable!("should have been s request"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_sender() {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
match tx.into() {
|
||||||
|
Message::Register(result) => {
|
||||||
|
let (req, _) = empty_request();
|
||||||
|
result.send(req.into()).unwrap();
|
||||||
|
match rx.recv().unwrap() {
|
||||||
|
Message::Req(_) => {}
|
||||||
|
_ => unreachable!("should have been a request"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!("should have been a register"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_sessionmessage() {
|
||||||
|
let id: Option<Field> = None;
|
||||||
|
let sess_msg: SessionMessage = id.into();
|
||||||
|
match sess_msg.into() {
|
||||||
|
Message::SessMsg(result) => match result {
|
||||||
|
SessionMessage::Validate(data) => assert!(data.is_none()),
|
||||||
|
_ => unreachable!("should have been a validate"),
|
||||||
|
},
|
||||||
|
_ => unreachable!("should have been a session message"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_backend_message() {
|
||||||
|
let data = BackEndMessage::Get;
|
||||||
|
match data.into() {
|
||||||
|
Message::BEMsg(result) => match result {
|
||||||
|
BackEndMessage::Get => {}
|
||||||
|
_ => unreachable!("should have been a validate"),
|
||||||
|
},
|
||||||
|
_ => unreachable!("should have been a session message"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Queue {
|
||||||
|
channels: Vec<Sender<Message>>,
|
||||||
|
rx: Receiver<Message>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Queue {
|
||||||
|
fn new(rx: Receiver<Message>) -> Self {
|
||||||
|
Self {
|
||||||
|
channels: Vec::new(),
|
||||||
|
rx: rx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn listen(&mut self) {
|
||||||
|
loop {
|
||||||
|
let msg = self.rx.recv().unwrap();
|
||||||
|
match msg {
|
||||||
|
Message::Register(tx) => self.channels.push(tx),
|
||||||
|
_ => {
|
||||||
|
for tx in self.channels.iter() {
|
||||||
|
tx.send(msg.clone()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start() -> Sender<Message> {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
spawn(move || {
|
||||||
|
let mut queue = Queue::new(rx);
|
||||||
|
queue.listen();
|
||||||
|
});
|
||||||
|
tx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod queues {
|
||||||
|
use super::*;
|
||||||
|
use crate::create_request::empty_request;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_queue() {
|
||||||
|
let mut channels = Vec::new();
|
||||||
|
for _ in 0..5 {
|
||||||
|
channels.push(channel());
|
||||||
|
}
|
||||||
|
let mut queue_tx = Queue::start();
|
||||||
|
for (tx, _) in channels.iter() {
|
||||||
|
queue_tx.send(tx.clone().into()).unwrap();
|
||||||
|
}
|
||||||
|
let (req, _) = empty_request();
|
||||||
|
queue_tx.send(req.into()).unwrap();
|
||||||
|
for (_, rx) in channels.iter() {
|
||||||
|
match rx.recv().unwrap() {
|
||||||
|
Message::Req(_) => {}
|
||||||
|
_ => unreachable!("should have been a request"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
258
src/queue.rs
258
src/queue.rs
@ -1,20 +1,224 @@
|
|||||||
use crate::{session2::SessionMessage, Request};
|
use crate::{client::Reply, ClientMessage, Request};
|
||||||
use std::{
|
use std::{
|
||||||
sync::mpsc::{channel, Receiver, Sender},
|
sync::mpsc::{channel, Receiver, Sender},
|
||||||
thread::spawn,
|
thread::spawn,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum MessageData {
|
||||||
|
ClientMsg(ClientMessage),
|
||||||
|
Register(Sender<Message>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ClientMessage> for MessageData {
|
||||||
|
fn from(value: ClientMessage) -> Self {
|
||||||
|
MessageData::ClientMsg(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Request> for MessageData {
|
||||||
|
fn from(value: Request) -> Self {
|
||||||
|
let data: ClientMessage = value.into();
|
||||||
|
MessageData::ClientMsg(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Sender<Message>> for MessageData {
|
||||||
|
fn from(value: Sender<Message>) -> Self {
|
||||||
|
MessageData::Register(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod messagedatas {
|
||||||
|
use crate::create_requests::root_doc_no_sess;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_client_message() {
|
||||||
|
let (req, _) = root_doc_no_sess();
|
||||||
|
let data: ClientMessage = req.into();
|
||||||
|
match data.into() {
|
||||||
|
MessageData::ClientMsg(_) => {},
|
||||||
|
_ => unreachable!("should have been a client messsage"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_request() {
|
||||||
|
let (req, _) = root_doc_no_sess();
|
||||||
|
match req.into() {
|
||||||
|
MessageData::ClientMsg(_) => {},
|
||||||
|
_ => unreachable!("should be a client message"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_sender() {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
match tx.into() {
|
||||||
|
MessageData::Register(result) => {
|
||||||
|
let (req, _) = root_doc_no_sess();
|
||||||
|
result.send(Message::new(req.into())).unwrap();
|
||||||
|
match rx.recv().unwrap().data {
|
||||||
|
MessageData::ClientMsg(_) => {}
|
||||||
|
_ => unreachable!("should have been a request"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!("should have been a register"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Message {
|
||||||
|
data: MessageData,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Message {
|
||||||
|
pub fn new(data: MessageData) -> Self {
|
||||||
|
Self {
|
||||||
|
data: data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_data(&self) -> &MessageData {
|
||||||
|
&self.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod messages {
|
||||||
|
use crate::create_requests::root_doc_no_sess;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_msg() {
|
||||||
|
let (req, _) = root_doc_no_sess();
|
||||||
|
let msg = Message::new(req.into());
|
||||||
|
match msg.data {
|
||||||
|
MessageData::ClientMsg(_) => {},
|
||||||
|
_ => unreachable!("should have been a client message"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Queue {
|
||||||
|
channels: Vec<Sender<Message>>,
|
||||||
|
rx: Receiver<Message>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Queue {
|
||||||
|
fn new(rx: Receiver<Message>) -> Self {
|
||||||
|
Self {
|
||||||
|
channels: Vec::new(),
|
||||||
|
rx: rx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start() -> Sender<Message> {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
spawn(move || {
|
||||||
|
let mut queue = Queue::new(rx);
|
||||||
|
queue.listen();
|
||||||
|
});
|
||||||
|
tx
|
||||||
|
}
|
||||||
|
|
||||||
|
fn listen(&mut self) {
|
||||||
|
loop {
|
||||||
|
let msg = self.rx.recv().unwrap();
|
||||||
|
match msg.get_data() {
|
||||||
|
MessageData::Register(sender) => self.channels.push(sender.clone()),
|
||||||
|
_ => {
|
||||||
|
for tx in self.channels.iter() {
|
||||||
|
tx.send(msg.clone()).unwrap();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod queues {
|
||||||
|
use crate::{
|
||||||
|
create_requests::root_doc_no_sess,
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
use std::time::Duration;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_queue() {
|
||||||
|
let mut channels = Vec::new();
|
||||||
|
for _ in 0..5 {
|
||||||
|
channels.push(channel());
|
||||||
|
}
|
||||||
|
let queue_tx = Queue::start();
|
||||||
|
for (tx, _) in channels.iter() {
|
||||||
|
queue_tx.send(Message::new(tx.clone().into())).unwrap();
|
||||||
|
}
|
||||||
|
let (req, _) = root_doc_no_sess();
|
||||||
|
queue_tx.send(Message::new(req.into())).unwrap();
|
||||||
|
for (_, rx) in channels.iter() {
|
||||||
|
match rx.recv_timeout(Duration::from_millis(500)).unwrap().get_data() {
|
||||||
|
MessageData::ClientMsg(_) => {}
|
||||||
|
_ => unreachable!("should have been a request"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#[test]
|
||||||
|
fn get_root_doc() {
|
||||||
|
let (client_tx, client_rx) = channel();
|
||||||
|
let sess = None;
|
||||||
|
let req = Request {
|
||||||
|
tx: client_tx,
|
||||||
|
session: sess,
|
||||||
|
};
|
||||||
|
let tx = Queue::start();
|
||||||
|
tx.send(Message::new(req.into())).unwrap();
|
||||||
|
client_rx.recv().unwrap();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
use crate::Request;
|
||||||
|
use std::{
|
||||||
|
sync::mpsc::{channel, Receiver, Sender},
|
||||||
|
thread::spawn,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub trait QueueClient: Sized {
|
||||||
|
fn new(tx: Sender<Message>, rx: Receiver<Message>) -> Self;
|
||||||
|
|
||||||
|
fn start(queue_tx: Sender<Message>) {
|
||||||
|
spawn(move || {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
let service = Self::new(queue_tx.clone(), rx);
|
||||||
|
queue_tx.send(tx.into()).unwrap();
|
||||||
|
service.listen();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_receiver(&self) -> &Receiver<Message>;
|
||||||
|
|
||||||
|
fn listen(&self) {
|
||||||
|
let rx = self.get_receiver();
|
||||||
|
loop {
|
||||||
|
rx.recv().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
Register(Sender<Message>),
|
Register(Sender<Message>),
|
||||||
Req(Request),
|
Req(Request),
|
||||||
SessMsg(SessionMessage),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Request> for Message {
|
|
||||||
fn from(value: Request) -> Self {
|
|
||||||
Message::Req(value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Sender<Message>> for Message {
|
impl From<Sender<Message>> for Message {
|
||||||
@ -23,22 +227,22 @@ impl From<Sender<Message>> for Message {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SessionMessage> for Message {
|
impl From<Request> for Message {
|
||||||
fn from(value: SessionMessage) -> Self {
|
fn from(value: Request) -> Self {
|
||||||
Message::SessMsg(value)
|
Message::Req(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod messages {
|
mod messages {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{create_request::empty_request, Field};
|
use crate::request_test_data::request_root_document;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn from_request() {
|
fn from_request() {
|
||||||
let (req, _) = empty_request();
|
let (req, _) = request_root_document();
|
||||||
match req.into() {
|
match req.into() {
|
||||||
Message::Req(result) => assert!(result.get_session().is_none()),
|
Message::Req(_) => {},
|
||||||
_ => unreachable!("should have been s request"),
|
_ => unreachable!("should have been s request"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,7 +252,7 @@ mod messages {
|
|||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
match tx.into() {
|
match tx.into() {
|
||||||
Message::Register(result) => {
|
Message::Register(result) => {
|
||||||
let (req, _) = empty_request();
|
let (req, _) = request_root_document();
|
||||||
result.send(req.into()).unwrap();
|
result.send(req.into()).unwrap();
|
||||||
match rx.recv().unwrap() {
|
match rx.recv().unwrap() {
|
||||||
Message::Req(_) => {}
|
Message::Req(_) => {}
|
||||||
@ -58,22 +262,9 @@ mod messages {
|
|||||||
_ => unreachable!("should have been a register"),
|
_ => unreachable!("should have been a register"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn from_sessionmessage() {
|
|
||||||
let id: Option<Field> = None;
|
|
||||||
let sess_msg: SessionMessage = id.into();
|
|
||||||
match sess_msg.into() {
|
|
||||||
Message::SessMsg(result) => match result {
|
|
||||||
SessionMessage::Validate(data) => assert!(data.is_none()),
|
|
||||||
_ => unreachable!("should have been a validate"),
|
|
||||||
},
|
|
||||||
_ => unreachable!("should have been a session message"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Queue {
|
pub struct Queue {
|
||||||
channels: Vec<Sender<Message>>,
|
channels: Vec<Sender<Message>>,
|
||||||
rx: Receiver<Message>,
|
rx: Receiver<Message>,
|
||||||
}
|
}
|
||||||
@ -100,7 +291,7 @@ impl Queue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start() -> Sender<Message> {
|
pub fn start() -> Sender<Message> {
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
spawn(move || {
|
spawn(move || {
|
||||||
let mut queue = Queue::new(rx);
|
let mut queue = Queue::new(rx);
|
||||||
@ -113,7 +304,7 @@ impl Queue {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod queues {
|
mod queues {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::create_request::empty_request;
|
use crate::request_test_data::request_root_document;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_queue() {
|
fn create_queue() {
|
||||||
@ -121,11 +312,11 @@ mod queues {
|
|||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
channels.push(channel());
|
channels.push(channel());
|
||||||
}
|
}
|
||||||
let mut queue_tx = Queue::start();
|
let queue_tx = Queue::start();
|
||||||
for (tx, _) in channels.iter() {
|
for (tx, _) in channels.iter() {
|
||||||
queue_tx.send(tx.clone().into()).unwrap();
|
queue_tx.send(tx.clone().into()).unwrap();
|
||||||
}
|
}
|
||||||
let (req, _) = empty_request();
|
let (req, _) = request_root_document();
|
||||||
queue_tx.send(req.into()).unwrap();
|
queue_tx.send(req.into()).unwrap();
|
||||||
for (_, rx) in channels.iter() {
|
for (_, rx) in channels.iter() {
|
||||||
match rx.recv().unwrap() {
|
match rx.recv().unwrap() {
|
||||||
@ -135,3 +326,4 @@ mod queues {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user