Compare commits

..

No commits in common. "28e6e7600856fceba2336c52f07115d357a4a0d1" and "0be4e33b36a17f1d73f5f8d6c56054cd73640e3e" have entirely different histories.

12 changed files with 780 additions and 387 deletions

661
Cargo.lock generated
View file

@ -2,28 +2,244 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "async-trait"
version = "0.1.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "autocfg"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "backtrace"
version = "0.3.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "bytes"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
[[package]]
name = "cc"
version = "1.0.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "env_logger"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
dependencies = [
"humantime",
"is-terminal",
"log",
"regex",
"termcolor",
]
[[package]]
name = "futures"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-executor"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-macro"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]] [[package]]
name = "gg-broadcast" name = "gg-broadcast"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"nebkor-maelstrom", "async-trait",
"maelstrom-node",
"serde_json", "serde_json",
"tokio",
] ]
[[package]] [[package]]
name = "gg-echo" name = "gg-echo"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"nebkor-maelstrom", "async-trait",
"serde_json", "maelstrom-node",
"tokio",
] ]
[[package]] [[package]]
name = "gg-uid" name = "gg-uid"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"nebkor-maelstrom", "async-trait",
"maelstrom-node",
"serde_json", "serde_json",
"tokio",
]
[[package]]
name = "gimli"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "is-terminal"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
dependencies = [
"hermit-abi",
"libc",
"windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -33,19 +249,130 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]] [[package]]
name = "nebkor-maelstrom" name = "libc"
version = "0.0.1" version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "lock_api"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [ dependencies = [
"serde", "autocfg",
"serde_json", "scopeguard",
"serde_repr",
] ]
[[package]] [[package]]
name = "proc-macro2" name = "log"
version = "1.0.83" version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "maelstrom-node"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f5c71562438987c4386067f65426150b918f2e000c7c851256ec8adea01b516"
dependencies = [
"async-trait",
"env_logger",
"futures",
"log",
"serde",
"serde_json",
"simple-error",
"tokio",
"tokio-context",
"tokio-util",
]
[[package]]
name = "memchr"
version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]]
name = "miniz_oxide"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"wasi",
"windows-sys 0.48.0",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "object"
version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
dependencies = [
"memchr",
]
[[package]]
name = "parking_lot"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets 0.52.5",
]
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "proc-macro2"
version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -59,12 +386,62 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "redox_syscall"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.18" 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 = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.202" version = "1.0.202"
@ -97,29 +474,273 @@ dependencies = [
] ]
[[package]] [[package]]
name = "serde_repr" name = "signal-hook-registry"
version = "0.1.19" version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
dependencies = [ dependencies = [
"proc-macro2", "libc",
"quote", ]
"syn",
[[package]]
name = "simple-error"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8542b68b8800c3cda649d2c72d688b6907b30f1580043135d61669d4aad1c175"
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "socket2"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
dependencies = [
"libc",
"windows-sys 0.52.0",
] ]
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.65" version = "2.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "tokio"
version = "1.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys 0.48.0",
]
[[package]]
name = "tokio-context"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaf0b8394dd5ca9a1b726c629390154c19222dfd7467a4b56f1ced90adee3958"
dependencies = [
"tokio",
]
[[package]]
name = "tokio-macros"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio-util"
version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.12" version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi-util"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.5",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
"windows_aarch64_gnullvm 0.52.5",
"windows_aarch64_msvc 0.52.5",
"windows_i686_gnu 0.52.5",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.5",
"windows_x86_64_gnu 0.52.5",
"windows_x86_64_gnullvm 0.52.5",
"windows_x86_64_msvc 0.52.5",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"

View file

@ -1,5 +1,5 @@
[workspace] [workspace]
members = ["gg-echo", "gg-uid", "gg-broadcast", "nebkor-maelstrom"] members = ["gg-echo", "gg-uid", "gg-broadcast"]
resolver = "2" resolver = "2"
[workspace.package] [workspace.package]
@ -8,4 +8,7 @@ authors = ["joe ardent"]
license-file = "LICENSE.md" license-file = "LICENSE.md"
[workspace.dependencies] [workspace.dependencies]
async-trait = "0.1"
maelstrom-node = "0.1"
tokio = { version = "1", default-features = false, features = ["io-util", "io-std", "rt-multi-thread", "macros"] }
serde_json = "1" serde_json = "1"

View file

@ -1,5 +1 @@
Working through the [Fly.io distributed systems challenge](https://fly.io/dist-sys/), in Rust. Working through the [Fly.io distributed systems challenge](https://fly.io/dist-sys/), in Rust.
The `nebkor-maelstrom` crate is meant to be roughly equivalent to the Go Maelstrom.Node package, and
provides serde-backed data structures for messages as well as runner for processing messages from
the Maelstrom network. See `gg-echo/src/main.rs` for the simplest possible use of it.

View file

@ -6,5 +6,7 @@ authors.workspace = true
license-file.workspace = true license-file.workspace = true
[dependencies] [dependencies]
async-trait.workspace = true
maelstrom-node.workspace = true
serde_json.workspace = true serde_json.workspace = true
nebkor-maelstrom = { path = "../nebkor-maelstrom" } tokio.workspace = true

View file

@ -1,21 +1,23 @@
use std::{collections::HashMap, rc::Rc, sync::Mutex}; use async_trait::async_trait;
use maelstrom::protocol::Message;
use maelstrom::{done, protocol::MessageBody, Node, Result, Runtime};
use serde_json::{Map, Value};
use std::borrow::BorrowMut;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use nebkor_maelstrom::{protocol::Payload, Body, Message, Node, Runner}; #[tokio::main]
async fn main() {
fn main() { let handler = Arc::new(BCaster::default());
let out = std::io::stdout().lock(); let _ = Runtime::new()
let input = std::io::stdin().lock(); .with_handler(handler)
.run()
let node = BCaster::default(); .await
let node = Rc::new(Mutex::new(node)); .unwrap_or_default();
let runner = Runner::new(out, node);
runner.run(input);
} }
type Store = HashMap<String, i64>; type Store = Arc<Mutex<HashMap<String, i64>>>;
type Gossips = HashMap<u64, Message>; type Gossips = Arc<Mutex<HashMap<(u64, String), MessageBody>>>;
#[derive(Clone, Default)] #[derive(Clone, Default)]
struct BCaster { struct BCaster {
@ -23,83 +25,96 @@ struct BCaster {
pub gossips: Gossips, pub gossips: Gossips,
} }
#[async_trait]
impl Node for BCaster { impl Node for BCaster {
fn handle(&mut self, runner: &Runner, req: &Message) { async fn process(&self, runtime: Runtime, req: Message) -> Result<()> {
let typ = req.body.typ.as_str(); let typ = req.get_type();
let frm = req.src.as_str(); let frm = req.src.as_str();
let mid = req.body.msg_id; let mid = req.body.msg_id;
let nid = runner.node_id(); let key = format!("{frm}{mid}");
let nid = nid.as_str();
let key = format!("{frm}-{mid}");
let key = key.as_str(); let key = key.as_str();
{ {
for (_, gossip) in self.gossips.iter() { let gossips: Vec<((_, String), MessageBody)> = {
runner.send(gossip.clone()); let g = self.gossips.lock().unwrap();
g.clone().into_iter().collect()
};
for ((_, node), gossip) in gossips.into_iter() {
runtime.send(node, gossip).await.unwrap_or_default();
} }
} }
match typ { match typ {
"gossip_ok" => {
let id = req.body.in_reply_to;
self.gossips.remove(&id);
}
"broadcast" => { "broadcast" => {
let val = req.body.payload.get("message").and_then(|v| v.as_i64()); let val = req.body.extra.get("message").and_then(|v| v.as_i64());
if let Some(val) = val { if let Some(val) = val {
{ {
// there's only one thread, safe to unwrap // there's only one thread, safe to unwrap
self.store.entry(key.to_owned()).or_insert(val); let mut guard = self.store.lock().unwrap();
guard.borrow_mut().entry(key.to_owned()).or_insert(val);
} }
let extra: Payload = [ let extra: Map<String, Value> = [
("key".to_string(), key.into()), ("key".to_string(), key.into()),
("val".to_string(), val.into()), ("val".to_string(), val.into()),
] ]
.into_iter() .into_iter()
.collect(); .collect();
let gossip = Body::from_type("gossip").with_payload(extra); let gossip = MessageBody::from_extra(extra).with_type("gossip");
for node in runner.nodes().iter().filter(|n| n.as_str() != nid) { for node in runtime.neighbours() {
let id = runner.next_msg_id(); let id = runtime.next_msg_id();
let gossip = gossip.clone().with_msg_id(id); let gossip = gossip.clone().and_msg_id(id);
let msg = Message { {
body: gossip, let mut g = self.gossips.lock().unwrap();
src: nid.to_string(), g.insert((id, node.to_owned()), gossip.clone());
dest: node.to_string(),
};
self.gossips.insert(id, msg.clone());
runner.send(msg);
} }
let body = Body::from_type("broadcast_ok"); runtime.send(node, gossip).await?;
runner.reply(req, body); }
let body = MessageBody::new().with_type("broadcast_ok");
return runtime.reply(req, body).await;
} }
} }
"read" => { "read" => {
let vals = self.store.values().cloned().collect::<Vec<_>>(); let vals = {
let g = self.store.lock().unwrap();
let payload: Payload = [("messages".to_string(), vals.into())] g.values().cloned().collect::<Vec<_>>()
};
let body = MessageBody::from_extra(
[("messages".to_string(), vals.into())]
.into_iter() .into_iter()
.collect(); .collect(),
let body = Body::from_type("read_ok").with_payload(payload); )
.with_type("read_ok");
runner.reply(req, body); return runtime.reply(req, body).await;
} }
"topology" => { "topology" => {
let body = Body::from_type("topology_ok"); let body = MessageBody::new().with_type("topology_ok");
runner.reply(req, body); return runtime.reply(req, body).await;
} }
"gossip" => { "gossip" => {
let key = req.body.payload.get("key").unwrap().as_str().unwrap(); let key = req.body.extra.get("key").unwrap().as_str().unwrap();
let val = req.body.payload.get("val").unwrap().as_i64().unwrap(); let val = req.body.extra.get("val").unwrap().as_i64().unwrap();
{
// there's only one thread, safe to unwrap
let mut guard = self.store.lock().unwrap();
guard.borrow_mut().entry(key.to_string()).or_insert(val);
}
let body = MessageBody::new().with_type("gossip_ok");
return runtime.reply(req, body).await;
}
"gossip_ok" => {
let id = req.body.in_reply_to;
let key = (id, frm.to_owned());
{
let mut g = self.gossips.lock().unwrap();
g.remove(&key);
}
}
_ => {}
}
self.store.entry(key.to_string()).or_insert(val); done(runtime, req)
let body = Body::from_type("gossip_ok");
runner.reply(req, body);
}
_ => {
eprintln!("unknown type: {req:?}");
}
}
} }
} }

View file

@ -5,5 +5,6 @@ version.workspace = true
authors.workspace = true authors.workspace = true
[dependencies] [dependencies]
serde_json.workspace = true async-trait.workspace = true
nebkor-maelstrom = { path = "../nebkor-maelstrom" } maelstrom-node.workspace = true
tokio.workspace = true

View file

@ -1,30 +1,29 @@
use std::{rc::Rc, sync::Mutex}; use async_trait::async_trait;
use maelstrom::protocol::Message;
use maelstrom::{done, Node, Result, Runtime};
use std::sync::Arc;
use nebkor_maelstrom::{Body, Message, Node, Runner}; #[tokio::main]
async fn main() {
struct Echo; let handler = Arc::new(Handler::default());
let _ = Runtime::new()
impl Node for Echo { .with_handler(handler)
fn handle(&mut self, runner: &Runner, msg: &Message) { .run()
let typ = &msg.body.typ; .await
match typ.as_str() { .unwrap_or_default();
"echo" => {
let body = Body::from_type("echo_ok").with_payload(msg.body.payload.clone());
runner.reply(&msg, body);
}
_ => {}
}
}
} }
fn main() { #[derive(Clone, Default)]
let out = std::io::stdout().lock(); struct Handler {}
let input = std::io::stdin().lock();
let node = Echo; #[async_trait]
let node = Rc::new(Mutex::new(node)); impl Node for Handler {
async fn process(&self, runtime: Runtime, req: Message) -> Result<()> {
let runner = Runner::new(out, node); if req.get_type() == "echo" {
let echo = req.body.clone().with_type("echo_ok");
runner.run(input); return runtime.reply(req, echo).await;
}
done(runtime, req)
}
} }

View file

@ -6,5 +6,7 @@ authors.workspace = true
license-file.workspace = true license-file.workspace = true
[dependencies] [dependencies]
async-trait.workspace = true
maelstrom-node.workspace = true
serde_json.workspace = true serde_json.workspace = true
nebkor-maelstrom = { path = "../nebkor-maelstrom" } tokio.workspace = true

View file

@ -1,35 +1,37 @@
use std::{rc::Rc, sync::Mutex}; use async_trait::async_trait;
use maelstrom::protocol::Message;
use maelstrom::{done, protocol::MessageBody, Node, Result, Runtime};
use serde_json::{Map, Value};
use std::sync::Arc;
use nebkor_maelstrom::{protocol::Payload, Body, Message, Node, Runner}; #[tokio::main]
async fn main() {
fn main() { let handler = Arc::new(Handler);
let out = std::io::stdout().lock(); let _ = Runtime::new()
let input = std::io::stdin().lock(); .with_handler(handler)
.run()
let node = GenUid; .await
let node = Rc::new(Mutex::new(node)); .unwrap_or_default();
let runner = Runner::new(out, node);
runner.run(input);
} }
#[derive(Clone, Default)] #[derive(Clone, Default)]
struct GenUid; struct Handler;
impl Node for GenUid { #[async_trait]
fn handle(&mut self, runner: &Runner, msg: &Message) { impl Node for Handler {
let id = runner.node_id(); async fn process(&self, runtime: Runtime, req: Message) -> Result<()> {
let mid = runner.next_msg_id(); let id = runtime.node_id();
if msg.body.typ == "generate" { let mid = runtime.next_msg_id();
let payload: Payload = [("id".to_string(), format!("{id}{mid}").into())] if req.get_type() == "generate" {
let extra: Map<String, Value> = [("id".to_string(), format!("{id}{mid}").into())]
.into_iter() .into_iter()
.collect(); .collect();
let body = Body::from_type("generate_ok") let body = MessageBody::from_extra(extra)
.with_msg_id(mid) .with_type("generate_ok")
.with_payload(payload); .and_msg_id(mid);
return runtime.reply(req, body).await;
}
runner.reply(msg, body); done(runtime, req)
}
} }
} }

View file

@ -1,11 +0,0 @@
[package]
name = "nebkor-maelstrom"
edition = "2021"
version.workspace = true
authors.workspace = true
license-file.workspace = true
[dependencies]
serde_json.workspace = true
serde = { version = "1", default-features = false, features = ["derive"] }
serde_repr = "0.1"

View file

@ -1,121 +0,0 @@
use std::{
cell::OnceCell,
io::{BufRead, StdinLock, StdoutLock, Write},
rc::Rc,
sync::{
atomic::{AtomicU64, Ordering},
Mutex,
},
};
pub mod protocol;
pub use protocol::{Body, Message};
pub type DynNode = Rc<Mutex<dyn Node>>;
pub trait Node {
fn handle(&mut self, runner: &Runner, msg: &Message);
}
pub struct Runner<'io> {
msg_id: AtomicU64,
node: DynNode,
node_id: OnceCell<String>,
nodes: OnceCell<Vec<String>>,
output: Mutex<StdoutLock<'io>>,
steps: AtomicU64,
}
impl<'io> Runner<'io> {
pub fn new(output: StdoutLock<'io>, node: DynNode) -> Self {
Runner {
output: Mutex::new(output),
node,
msg_id: AtomicU64::new(1),
nodes: OnceCell::new(),
node_id: OnceCell::new(),
steps: AtomicU64::new(0),
}
}
pub fn run(&self, input: StdinLock) {
for line in input.lines().map_while(Result::ok) {
if let Ok(msg) = serde_json::from_str::<Message>(&line) {
let typ = &msg.body.typ;
if let "init" = typ.as_str() {
self.init(&msg);
let body = Body::from_type("init_ok");
self.reply(&msg, body);
} else {
let mut n = self.node.lock().unwrap();
n.handle(self, &msg);
}
}
self.steps.fetch_add(1, Ordering::SeqCst);
}
}
pub fn node_id(&self) -> String {
self.node_id.get().cloned().unwrap_or_default()
}
pub fn next_msg_id(&self) -> u64 {
self.msg_id.fetch_add(1, Ordering::SeqCst)
}
pub fn nodes(&self) -> &[String] {
self.nodes.get().unwrap()
}
pub fn init(&self, msg: &Message) {
let node_id = msg
.body
.payload
.get("node_id")
.unwrap()
.as_str()
.unwrap()
.to_owned();
let nodes = msg
.body
.payload
.get("node_ids")
.unwrap()
.as_array()
.unwrap()
.iter()
.map(|s| s.as_str().unwrap().to_string())
.collect::<Vec<_>>();
let _ = self.node_id.get_or_init(|| node_id.to_owned());
let _ = self.nodes.get_or_init(|| nodes.to_vec());
}
pub fn reply(&self, req: &Message, body: Body) {
let mut body = body;
let src = self.node_id.get().unwrap().to_owned();
let dest = req.src.clone();
let in_reply_to = req.body.msg_id;
body.in_reply_to = in_reply_to;
let msg = Message { src, dest, body };
self.send(msg);
}
pub fn send(&self, msg: Message) {
let mut msg = msg;
if msg.body.msg_id == 0 {
let mid = self.next_msg_id();
msg.body.msg_id = mid;
}
let msg = serde_json::to_string(&msg).unwrap();
self.writeln(&msg);
}
fn writeln(&self, msg: &str) {
let mut out = self.output.lock().unwrap();
let msg = format!("{msg}\n");
out.write_all(msg.as_bytes()).unwrap();
out.flush().unwrap();
}
}

View file

@ -1,116 +0,0 @@
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use serde_repr::{Deserialize_repr, Serialize_repr};
pub type Payload = Map<String, Value>;
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct Message {
pub src: String,
pub dest: String,
pub body: Body,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct Body {
#[serde(rename = "type")]
pub typ: String,
#[serde(default, skip_serializing_if = "u64_zero_by_ref")]
pub msg_id: u64,
#[serde(default, skip_serializing_if = "u64_zero_by_ref")]
pub in_reply_to: u64,
#[serde(flatten)]
pub payload: Payload,
}
impl Body {
pub fn from_type(typ: &str) -> Self {
Body {
typ: typ.to_string(),
..Default::default()
}
}
pub fn with_msg_id(self, msg_id: u64) -> Self {
let mut b = self;
b.msg_id = msg_id;
b
}
pub fn with_in_reply_to(self, in_reply_to: u64) -> Self {
let mut b = self;
b.in_reply_to = in_reply_to;
b
}
pub fn with_payload(self, payload: Payload) -> Self {
let mut b = self;
b.payload = payload;
b
}
}
pub fn init_ok(msg_id: u64, in_reply_to: u64) -> Body {
Body::from_type("init_ok")
.with_msg_id(msg_id)
.with_in_reply_to(in_reply_to)
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ErrorCode {
Definite(DefiniteError),
Indefinite(IndefiniteError),
}
#[derive(Debug, Clone, Serialize_repr, Deserialize_repr)]
#[repr(u64)]
pub enum DefiniteError {
NodeNotFound = 2,
NotSupported = 10,
TemporarilyUnavailable = 11,
MalformedRequest = 12,
Abort = 14,
KeyNotFound = 20,
KeyAlreadyExists = 21,
PreconditionFailed = 22,
TxnConflict = 30,
}
#[derive(Debug, Clone, Serialize_repr, Deserialize_repr)]
#[repr(u64)]
pub enum IndefiniteError {
Timeout = 0,
Crash = 13,
}
pub fn error(msg_id: u64, in_reply_to: u64, code: ErrorCode, text: Option<&str>) -> Body {
Body {
typ: "error".to_string(),
msg_id,
in_reply_to,
payload: [
("code".to_string(), serde_json::to_value(code).unwrap()),
("text".to_string(), serde_json::to_value(text).unwrap()),
]
.into_iter()
.collect(),
}
}
#[allow(clippy::trivially_copy_pass_by_ref)]
fn u64_zero_by_ref(num: &u64) -> bool {
*num == 0
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn error_codes() {
let ec = ErrorCode::Definite(DefiniteError::Abort);
let e = serde_json::to_string(&ec).unwrap();
assert_eq!(&e, "14");
}
}