thing-contract: the gamecult.thing.* kinds as CultCache entries and unions (first commit, build not yet verified)
Does not build-verified at this commit; tests follow. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d8f5e1f2fe
commit
852c34b60a
12 changed files with 1933 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -25,3 +25,4 @@ flutter/eve_parity/assets/repixelizer/
|
|||
*.deb
|
||||
*.ipa
|
||||
*.dSYM/
|
||||
/target
|
||||
|
|
|
|||
602
Cargo.lock
generated
Normal file
602
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,602 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6651c9ed80effdc7db0ff72512157f901af5e3549e341e24b1dd4887d836d838"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
|
||||
dependencies = [
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "cultcache-rs"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/GameCult/CultLib.git?rev=b3bd8dd5e5b208b2012392e9c5d6dfee2441aaa7#b3bd8dd5e5b208b2012392e9c5d6dfee2441aaa7"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"cultcache-rs-derive",
|
||||
"fs2",
|
||||
"redb",
|
||||
"rmp-serde",
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
"serde_json",
|
||||
"uuid",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cultcache-rs-derive"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/GameCult/CultLib.git?rev=b3bd8dd5e5b208b2012392e9c5d6dfee2441aaa7#b3bd8dd5e5b208b2012392e9c5d6dfee2441aaa7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484"
|
||||
|
||||
[[package]]
|
||||
name = "fs2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-util",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.190"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||
|
||||
[[package]]
|
||||
name = "redb"
|
||||
version = "4.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb338a6c67830a61bed824b78c2bb034ab1ff401a20616bd7957524f4fdc2f22"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rmp"
|
||||
version = "0.8.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rmp-serde"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155"
|
||||
dependencies = [
|
||||
"rmp",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_bytes"
|
||||
version = "0.11.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.154"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.119"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01016da373cd8f7ef12624f796309f5c31ba8d646dd08856c02cd741d823c622"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thing-contract"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cultcache-rs",
|
||||
"rmp-serde",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cc1186384beb7dd8eedea376413fd654937285ea6c9cfbb928dc3043ea4b606"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.129"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.129"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.129"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.8",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.129"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
||||
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[workspace]
|
||||
members = ["crates/*"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.dependencies]
|
||||
anyhow = "1"
|
||||
cultcache-rs = { git = "https://github.com/GameCult/CultLib.git", rev = "b3bd8dd5e5b208b2012392e9c5d6dfee2441aaa7", package = "cultcache-rs" }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
rmp-serde = "1.3"
|
||||
14
crates/thing-contract/Cargo.toml
Normal file
14
crates/thing-contract/Cargo.toml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "thing-contract"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
cultcache-rs = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
rmp-serde = { workspace = true }
|
||||
38
crates/thing-contract/src/asset.rs
Normal file
38
crates/thing-contract/src/asset.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
//! An asset catalog: the images a provider's surfaces reference by catalog id and asset id.
|
||||
|
||||
use cultcache_rs::{CultSlots, DatabaseEntry};
|
||||
|
||||
use crate::keys::{ProviderId, asset_catalog_key};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct AssetEntry {
|
||||
#[cultcache(key = 0)]
|
||||
pub id: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub media_type: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub uri: String,
|
||||
#[cultcache(key = 3)]
|
||||
pub width: i32,
|
||||
#[cultcache(key = 4)]
|
||||
pub height: i32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DatabaseEntry)]
|
||||
#[cultcache(type = "gamecult.thing.asset_catalog", schema = "gamecult.thing.asset_catalog.v1")]
|
||||
pub struct AssetCatalog {
|
||||
#[cultcache(key = 0)]
|
||||
pub provider_id: ProviderId,
|
||||
#[cultcache(key = 1)]
|
||||
pub catalog_id: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub version: i64,
|
||||
#[cultcache(key = 3)]
|
||||
pub assets: Vec<AssetEntry>,
|
||||
}
|
||||
|
||||
impl AssetCatalog {
|
||||
pub fn record_key(&self) -> String {
|
||||
asset_catalog_key(&self.provider_id, &self.catalog_id)
|
||||
}
|
||||
}
|
||||
120
crates/thing-contract/src/command.rs
Normal file
120
crates/thing-contract/src/command.rs
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
//! Commands: what a surface declares, and the one envelope a consumer sends. The caller's
|
||||
//! identity has no field here: the transport sets it.
|
||||
|
||||
use cultcache_rs::{CultSlots, CultUnion, DatabaseEntry};
|
||||
|
||||
use crate::keys::{CommandId, NodeId, SchemaId, invocation_key};
|
||||
use crate::source::ParamName;
|
||||
|
||||
/// A command a surface declares. A node may reference only a declared command.
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct CommandDecl {
|
||||
#[cultcache(key = 0)]
|
||||
pub id: CommandId,
|
||||
#[cultcache(key = 1)]
|
||||
pub payload_schema: SchemaId,
|
||||
/// The input nodes whose current values travel with an invocation.
|
||||
#[cultcache(key = 2)]
|
||||
pub captures: Vec<NodeId>,
|
||||
#[cultcache(key = 3)]
|
||||
pub confirm: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct CommandIdRef {
|
||||
#[cultcache(key = 0)]
|
||||
pub id: CommandId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum CommandRef {
|
||||
#[cultcache(key = 0)]
|
||||
Id(CommandIdRef),
|
||||
#[cultcache(key = 1)]
|
||||
Param(ParamName),
|
||||
}
|
||||
|
||||
/// A typed record of the declared `payload_schema`, as its MessagePack bytes.
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct RecordPayload {
|
||||
#[cultcache(key = 0)]
|
||||
pub schema: SchemaId,
|
||||
#[cultcache(key = 1, bytes)]
|
||||
pub bytes: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct TextValue {
|
||||
#[cultcache(key = 0)]
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct NumberValue {
|
||||
#[cultcache(key = 0)]
|
||||
pub value: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct BoolValue {
|
||||
#[cultcache(key = 0)]
|
||||
pub value: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct ChoiceValue {
|
||||
#[cultcache(key = 0)]
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum InputValue {
|
||||
#[cultcache(key = 0)]
|
||||
Text(TextValue),
|
||||
#[cultcache(key = 1)]
|
||||
Number(NumberValue),
|
||||
#[cultcache(key = 2)]
|
||||
Bool(BoolValue),
|
||||
#[cultcache(key = 3)]
|
||||
Choice(ChoiceValue),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct CapturedInput {
|
||||
#[cultcache(key = 0)]
|
||||
pub node: NodeId,
|
||||
#[cultcache(key = 1)]
|
||||
pub value: InputValue,
|
||||
}
|
||||
|
||||
/// A consumer's request that a provider run a declared command.
|
||||
#[derive(Clone, Debug, PartialEq, DatabaseEntry)]
|
||||
#[cultcache(type = "gamecult.thing.command_invocation", schema = "gamecult.thing.command_invocation.v1")]
|
||||
pub struct CommandInvocation {
|
||||
/// A UUID string, unique per invocation.
|
||||
#[cultcache(key = 0)]
|
||||
pub invocation_id: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub surface_key: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub surface_version: i64,
|
||||
#[cultcache(key = 3)]
|
||||
pub command: CommandId,
|
||||
#[cultcache(key = 4)]
|
||||
pub payload: RecordPayload,
|
||||
#[cultcache(key = 5)]
|
||||
pub captured: Vec<CapturedInput>,
|
||||
#[cultcache(key = 6)]
|
||||
pub client: String,
|
||||
/// RFC 3339, UTC.
|
||||
#[cultcache(key = 7)]
|
||||
pub issued_at: String,
|
||||
#[cultcache(key = 8)]
|
||||
pub delegation: Option<String>,
|
||||
}
|
||||
|
||||
impl CommandInvocation {
|
||||
pub fn record_key(&self) -> String {
|
||||
invocation_key(&self.invocation_id)
|
||||
}
|
||||
}
|
||||
63
crates/thing-contract/src/keys.rs
Normal file
63
crates/thing-contract/src/keys.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
//! Identifier newtypes and the record key of each kind. No caller spells a key as a free string.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
macro_rules! id_type {
|
||||
($(#[$doc:meta])* $name:ident) => {
|
||||
$(#[$doc])*
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct $name(String);
|
||||
|
||||
impl $name {
|
||||
pub fn new(value: impl Into<String>) -> Self {
|
||||
Self(value.into())
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
id_type!(
|
||||
/// A provider of surfaces and state.
|
||||
ProviderId
|
||||
);
|
||||
id_type!(
|
||||
/// The schema id of a CultCache entry type, for example `gamecult.thing.surface.v1`.
|
||||
SchemaId
|
||||
);
|
||||
id_type!(
|
||||
/// The record key of a state record.
|
||||
RecordKey
|
||||
);
|
||||
id_type!(
|
||||
/// A node id, unique within its document after composition expansion.
|
||||
NodeId
|
||||
);
|
||||
id_type!(
|
||||
/// A command declared by a surface.
|
||||
CommandId
|
||||
);
|
||||
|
||||
pub(crate) fn surface_key(provider: &ProviderId, label: &str) -> String {
|
||||
format!("thing:surface:{}.{}", provider.as_str(), label)
|
||||
}
|
||||
|
||||
pub(crate) fn composition_key(publisher: &str, name: &str, version: i32) -> String {
|
||||
format!("thing:composition:{publisher}.{name}.v{version}")
|
||||
}
|
||||
|
||||
pub(crate) fn invocation_key(invocation_id: &str) -> String {
|
||||
format!("thing:invocation:{invocation_id}")
|
||||
}
|
||||
|
||||
pub(crate) fn result_key(invocation_id: &str, seq: i32) -> String {
|
||||
format!("thing:result:{invocation_id}.{seq}")
|
||||
}
|
||||
|
||||
pub(crate) fn asset_catalog_key(provider: &ProviderId, catalog_id: &str) -> String {
|
||||
format!("thing:assets:{}.{}", provider.as_str(), catalog_id)
|
||||
}
|
||||
37
crates/thing-contract/src/lib.rs
Normal file
37
crates/thing-contract/src/lib.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
//! The `gamecult.thing.*` wire types and their bytes. This crate owns the contract: the
|
||||
//! golden payloads it blesses are what every other language package and core are held to.
|
||||
//!
|
||||
//! Every kind is a CultCache `DatabaseEntry`; every closed set is a `CultUnion` written
|
||||
//! `[armKey, [slots...]]`, the shape the C# reference reads and writes.
|
||||
|
||||
mod asset;
|
||||
mod command;
|
||||
mod keys;
|
||||
mod node;
|
||||
mod result;
|
||||
mod source;
|
||||
mod style;
|
||||
|
||||
pub use asset::*;
|
||||
pub use command::*;
|
||||
pub use keys::{CommandId, NodeId, ProviderId, RecordKey, SchemaId};
|
||||
pub use node::*;
|
||||
pub use result::*;
|
||||
pub use source::*;
|
||||
pub use style::*;
|
||||
|
||||
use cultcache_rs::{CultCache, CultCacheRegistry};
|
||||
|
||||
/// Registers the five kinds with a cache.
|
||||
pub struct ThingContract;
|
||||
|
||||
impl CultCacheRegistry for ThingContract {
|
||||
fn register_entries(&self, cache: &mut CultCache) -> anyhow::Result<()> {
|
||||
cache.register_entry_type::<SurfaceDocument>()?;
|
||||
cache.register_entry_type::<CompositionDocument>()?;
|
||||
cache.register_entry_type::<CommandInvocation>()?;
|
||||
cache.register_entry_type::<CommandResult>()?;
|
||||
cache.register_entry_type::<AssetCatalog>()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
454
crates/thing-contract/src/node.rs
Normal file
454
crates/thing-contract/src/node.rs
Normal file
|
|
@ -0,0 +1,454 @@
|
|||
//! Thing Script: the closed node union, the surface document that holds a tree of nodes, and the
|
||||
//! composition document that names a reusable subtree. Arm keys are fixed for v1.
|
||||
|
||||
use cultcache_rs::{CultSlots, CultUnion, DatabaseEntry};
|
||||
|
||||
use crate::command::{CommandDecl, CommandRef};
|
||||
use crate::keys::{NodeId, ProviderId, composition_key, surface_key};
|
||||
use crate::source::{Bind, BoolSource, CollectionSource, MemberPath, NumberSource, TextSource};
|
||||
use crate::style::{BoxStyle, Paint, Role};
|
||||
|
||||
/// What every node carries.
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct NodeCommon {
|
||||
#[cultcache(key = 0)]
|
||||
pub id: NodeId,
|
||||
#[cultcache(key = 1)]
|
||||
pub visible: BoolSource,
|
||||
#[cultcache(key = 2)]
|
||||
pub a11y_label: Option<TextSource>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum Node {
|
||||
#[cultcache(key = 0)]
|
||||
Box(BoxNode),
|
||||
#[cultcache(key = 1)]
|
||||
Text(TextNode),
|
||||
#[cultcache(key = 2)]
|
||||
Image(ImageNode),
|
||||
#[cultcache(key = 3)]
|
||||
Button(ButtonNode),
|
||||
#[cultcache(key = 4)]
|
||||
Toggle(ToggleNode),
|
||||
#[cultcache(key = 5)]
|
||||
Slider(SliderNode),
|
||||
#[cultcache(key = 6)]
|
||||
TextInput(TextInputNode),
|
||||
#[cultcache(key = 7)]
|
||||
Select(SelectNode),
|
||||
#[cultcache(key = 8)]
|
||||
Repeat(RepeatNode),
|
||||
#[cultcache(key = 9)]
|
||||
Overlay(OverlayNode),
|
||||
#[cultcache(key = 10)]
|
||||
Plot(PlotNode),
|
||||
#[cultcache(key = 11)]
|
||||
Embed(EmbedNode),
|
||||
#[cultcache(key = 12)]
|
||||
Use(UseNode),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct BoxNode {
|
||||
#[cultcache(key = 0)]
|
||||
pub common: NodeCommon,
|
||||
#[cultcache(key = 1)]
|
||||
pub style: BoxStyle,
|
||||
#[cultcache(key = 2)]
|
||||
pub paint: Paint,
|
||||
#[cultcache(key = 3)]
|
||||
pub role: Role,
|
||||
#[cultcache(key = 4)]
|
||||
pub children: Vec<Node>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct TextNode {
|
||||
#[cultcache(key = 0)]
|
||||
pub common: NodeCommon,
|
||||
#[cultcache(key = 1)]
|
||||
pub content: TextSource,
|
||||
#[cultcache(key = 2)]
|
||||
pub style_token: String,
|
||||
#[cultcache(key = 3)]
|
||||
pub wrap: bool,
|
||||
#[cultcache(key = 4)]
|
||||
pub max_lines: Option<i32>,
|
||||
#[cultcache(key = 5)]
|
||||
pub selectable: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum ImageFit {
|
||||
#[cultcache(key = 0)]
|
||||
Contain,
|
||||
#[cultcache(key = 1)]
|
||||
Cover,
|
||||
#[cultcache(key = 2)]
|
||||
Fill,
|
||||
#[cultcache(key = 3)]
|
||||
Unscaled,
|
||||
}
|
||||
|
||||
/// An asset of a catalog, with the alternative text a reader without the picture needs.
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct ImageNode {
|
||||
#[cultcache(key = 0)]
|
||||
pub common: NodeCommon,
|
||||
#[cultcache(key = 1)]
|
||||
pub catalog: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub asset: String,
|
||||
#[cultcache(key = 3)]
|
||||
pub fit: ImageFit,
|
||||
#[cultcache(key = 4)]
|
||||
pub alt: TextSource,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct ButtonNode {
|
||||
#[cultcache(key = 0)]
|
||||
pub common: NodeCommon,
|
||||
#[cultcache(key = 1)]
|
||||
pub content: Vec<Node>,
|
||||
#[cultcache(key = 2)]
|
||||
pub on_activate: CommandRef,
|
||||
#[cultcache(key = 3)]
|
||||
pub enabled: BoolSource,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct ToggleNode {
|
||||
#[cultcache(key = 0)]
|
||||
pub common: NodeCommon,
|
||||
#[cultcache(key = 1)]
|
||||
pub checked: BoolSource,
|
||||
#[cultcache(key = 2)]
|
||||
pub on_change: CommandRef,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct SliderNode {
|
||||
#[cultcache(key = 0)]
|
||||
pub common: NodeCommon,
|
||||
#[cultcache(key = 1)]
|
||||
pub min: f64,
|
||||
#[cultcache(key = 2)]
|
||||
pub max: f64,
|
||||
#[cultcache(key = 3)]
|
||||
pub step: f64,
|
||||
#[cultcache(key = 4)]
|
||||
pub value: NumberSource,
|
||||
#[cultcache(key = 5)]
|
||||
pub commit: CommandRef,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum InputKind {
|
||||
#[cultcache(key = 0)]
|
||||
Text,
|
||||
#[cultcache(key = 1)]
|
||||
Number,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct TextInputNode {
|
||||
#[cultcache(key = 0)]
|
||||
pub common: NodeCommon,
|
||||
#[cultcache(key = 1)]
|
||||
pub multiline: bool,
|
||||
#[cultcache(key = 2)]
|
||||
pub kind: InputKind,
|
||||
#[cultcache(key = 3)]
|
||||
pub placeholder: TextSource,
|
||||
#[cultcache(key = 4)]
|
||||
pub initial: TextSource,
|
||||
#[cultcache(key = 5)]
|
||||
pub submit: CommandRef,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct SelectOption {
|
||||
#[cultcache(key = 0)]
|
||||
pub value: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub label: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct LiteralOptions {
|
||||
#[cultcache(key = 0)]
|
||||
pub options: Vec<SelectOption>,
|
||||
}
|
||||
|
||||
/// Options read from a collection: each item's value and label are members of the item.
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct BoundOptions {
|
||||
#[cultcache(key = 0)]
|
||||
pub collection: CollectionSource,
|
||||
#[cultcache(key = 1)]
|
||||
pub value_member: MemberPath,
|
||||
#[cultcache(key = 2)]
|
||||
pub label_member: MemberPath,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum OptionList {
|
||||
#[cultcache(key = 0)]
|
||||
Literal(LiteralOptions),
|
||||
#[cultcache(key = 1)]
|
||||
Bound(BoundOptions),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct SelectNode {
|
||||
#[cultcache(key = 0)]
|
||||
pub common: NodeCommon,
|
||||
#[cultcache(key = 1)]
|
||||
pub options: OptionList,
|
||||
#[cultcache(key = 2)]
|
||||
pub value: Bind,
|
||||
#[cultcache(key = 3)]
|
||||
pub on_change: CommandRef,
|
||||
}
|
||||
|
||||
/// The template is instantiated once per item of the collection, keyed by `key_member` of the item.
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct RepeatNode {
|
||||
#[cultcache(key = 0)]
|
||||
pub common: NodeCommon,
|
||||
#[cultcache(key = 1)]
|
||||
pub collection: CollectionSource,
|
||||
#[cultcache(key = 2)]
|
||||
pub key_member: MemberPath,
|
||||
#[cultcache(key = 3)]
|
||||
pub template: std::boxed::Box<Node>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct AnchorNode {
|
||||
#[cultcache(key = 0)]
|
||||
pub node: NodeId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum Anchor {
|
||||
#[cultcache(key = 0)]
|
||||
Viewport,
|
||||
#[cultcache(key = 1)]
|
||||
Node(AnchorNode),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct OverlayNode {
|
||||
#[cultcache(key = 0)]
|
||||
pub common: NodeCommon,
|
||||
#[cultcache(key = 1)]
|
||||
pub anchor: Anchor,
|
||||
#[cultcache(key = 2)]
|
||||
pub modal: bool,
|
||||
#[cultcache(key = 3)]
|
||||
pub dismiss: CommandRef,
|
||||
#[cultcache(key = 4)]
|
||||
pub children: Vec<Node>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum PlotMark {
|
||||
#[cultcache(key = 0)]
|
||||
Line,
|
||||
#[cultcache(key = 1)]
|
||||
Bar,
|
||||
#[cultcache(key = 2)]
|
||||
Area,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct PlotNode {
|
||||
#[cultcache(key = 0)]
|
||||
pub common: NodeCommon,
|
||||
/// A numeric list member of a record.
|
||||
#[cultcache(key = 1)]
|
||||
pub series: Bind,
|
||||
#[cultcache(key = 2)]
|
||||
pub mark: PlotMark,
|
||||
#[cultcache(key = 3)]
|
||||
pub x_min: Option<f64>,
|
||||
#[cultcache(key = 4)]
|
||||
pub x_max: Option<f64>,
|
||||
#[cultcache(key = 5)]
|
||||
pub y_min: Option<f64>,
|
||||
#[cultcache(key = 6)]
|
||||
pub y_max: Option<f64>,
|
||||
}
|
||||
|
||||
/// A leaf the host draws: `slot_kind` is a name the host declares it supports.
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct EmbedNode {
|
||||
#[cultcache(key = 0)]
|
||||
pub common: NodeCommon,
|
||||
#[cultcache(key = 1)]
|
||||
pub slot_kind: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub slot_id: String,
|
||||
#[cultcache(key = 3)]
|
||||
pub width: f64,
|
||||
#[cultcache(key = 4)]
|
||||
pub height: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct CompositionRef {
|
||||
#[cultcache(key = 0)]
|
||||
pub publisher: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub name: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub version: i32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct UseNode {
|
||||
#[cultcache(key = 0)]
|
||||
pub common: NodeCommon,
|
||||
#[cultcache(key = 1)]
|
||||
pub composition: CompositionRef,
|
||||
#[cultcache(key = 2)]
|
||||
pub args: Vec<Arg>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct Arg {
|
||||
#[cultcache(key = 0)]
|
||||
pub name: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub value: ArgValue,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct TextArg {
|
||||
#[cultcache(key = 0)]
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct NumberArg {
|
||||
#[cultcache(key = 0)]
|
||||
pub value: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct BoolArg {
|
||||
#[cultcache(key = 0)]
|
||||
pub value: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct CollectionArg {
|
||||
#[cultcache(key = 0)]
|
||||
pub source: CollectionSource,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct CommandArg {
|
||||
#[cultcache(key = 0)]
|
||||
pub command: CommandRef,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct SlotArg {
|
||||
#[cultcache(key = 0)]
|
||||
pub nodes: Vec<Node>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum ArgValue {
|
||||
#[cultcache(key = 0)]
|
||||
Text(TextArg),
|
||||
#[cultcache(key = 1)]
|
||||
Number(NumberArg),
|
||||
#[cultcache(key = 2)]
|
||||
Bool(BoolArg),
|
||||
#[cultcache(key = 3)]
|
||||
Bind(Bind),
|
||||
#[cultcache(key = 4)]
|
||||
Collection(CollectionArg),
|
||||
#[cultcache(key = 5)]
|
||||
Command(CommandArg),
|
||||
#[cultcache(key = 6)]
|
||||
Slot(SlotArg),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum ParamKind {
|
||||
#[cultcache(key = 0)]
|
||||
Text,
|
||||
#[cultcache(key = 1)]
|
||||
Number,
|
||||
#[cultcache(key = 2)]
|
||||
Bool,
|
||||
#[cultcache(key = 3)]
|
||||
Bind,
|
||||
#[cultcache(key = 4)]
|
||||
Collection,
|
||||
#[cultcache(key = 5)]
|
||||
Command,
|
||||
#[cultcache(key = 6)]
|
||||
Slot,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct ParamDecl {
|
||||
#[cultcache(key = 0)]
|
||||
pub name: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub kind: ParamKind,
|
||||
}
|
||||
|
||||
/// A provider's surface: a tree of nodes and the commands it declares. A change of structure
|
||||
/// republishes the record with a higher `version`.
|
||||
#[derive(Clone, Debug, PartialEq, DatabaseEntry)]
|
||||
#[cultcache(type = "gamecult.thing.surface", schema = "gamecult.thing.surface.v1")]
|
||||
pub struct SurfaceDocument {
|
||||
#[cultcache(key = 0)]
|
||||
pub provider_id: ProviderId,
|
||||
#[cultcache(key = 1)]
|
||||
pub label: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub version: i64,
|
||||
#[cultcache(key = 3)]
|
||||
pub title: String,
|
||||
#[cultcache(key = 4)]
|
||||
pub root: Node,
|
||||
#[cultcache(key = 5)]
|
||||
pub commands: Vec<CommandDecl>,
|
||||
}
|
||||
|
||||
impl SurfaceDocument {
|
||||
pub fn record_key(&self) -> String {
|
||||
surface_key(&self.provider_id, &self.label)
|
||||
}
|
||||
}
|
||||
|
||||
/// A reusable subtree with typed parameters. Compositions never own commands.
|
||||
#[derive(Clone, Debug, PartialEq, DatabaseEntry)]
|
||||
#[cultcache(type = "gamecult.thing.composition", schema = "gamecult.thing.composition.v1")]
|
||||
pub struct CompositionDocument {
|
||||
#[cultcache(key = 0)]
|
||||
pub publisher: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub name: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub version: i32,
|
||||
#[cultcache(key = 3)]
|
||||
pub params: Vec<ParamDecl>,
|
||||
#[cultcache(key = 4)]
|
||||
pub body: Node,
|
||||
}
|
||||
|
||||
impl CompositionDocument {
|
||||
pub fn record_key(&self) -> String {
|
||||
composition_key(&self.publisher, &self.name, self.version)
|
||||
}
|
||||
}
|
||||
185
crates/thing-contract/src/result.rs
Normal file
185
crates/thing-contract/src/result.rs
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
//! The answer to a command invocation. A `CommandResult` is built only by its four
|
||||
//! constructors, each of which copies the invocation's id, and is read through accessors.
|
||||
//! Nothing here takes a state as a string, and nothing builds a result from a map.
|
||||
|
||||
use cultcache_rs::{CultSlots, CultUnion, DatabaseEntry};
|
||||
|
||||
use crate::command::{CommandInvocation, CommandRef};
|
||||
use crate::keys::{NodeId, result_key};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct PendingOutcome {
|
||||
#[cultcache(key = 0)]
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct CompletedOutcome {
|
||||
#[cultcache(key = 0)]
|
||||
pub source_version: Option<i64>,
|
||||
/// Whether the captured drafts of the invocation clear.
|
||||
#[cultcache(key = 1)]
|
||||
pub clear_drafts: bool,
|
||||
#[cultcache(key = 2)]
|
||||
pub effect: Option<Effect>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct DeniedOutcome {
|
||||
#[cultcache(key = 0)]
|
||||
pub reason: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub node: Option<NodeId>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct FailedOutcome {
|
||||
#[cultcache(key = 0)]
|
||||
pub reason: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum Outcome {
|
||||
#[cultcache(key = 0)]
|
||||
Pending(PendingOutcome),
|
||||
#[cultcache(key = 1)]
|
||||
Completed(CompletedOutcome),
|
||||
#[cultcache(key = 2)]
|
||||
Denied(DeniedOutcome),
|
||||
#[cultcache(key = 3)]
|
||||
Failed(FailedOutcome),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct OpenSurfaceEffect {
|
||||
#[cultcache(key = 0)]
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct OpenExternalEffect {
|
||||
#[cultcache(key = 0)]
|
||||
pub url: String,
|
||||
/// The command run when the external step returns.
|
||||
#[cultcache(key = 1)]
|
||||
pub resume: CommandRef,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum Effect {
|
||||
#[cultcache(key = 0)]
|
||||
OpenSurface(OpenSurfaceEffect),
|
||||
#[cultcache(key = 1)]
|
||||
OpenExternal(OpenExternalEffect),
|
||||
}
|
||||
|
||||
/// A provider's answer to one invocation. `seq` counts from 1 per invocation.
|
||||
///
|
||||
/// The positive case, a result built by a constructor from the invocation it answers:
|
||||
///
|
||||
/// ```
|
||||
/// use thing_contract::{CommandInvocation, CommandResult};
|
||||
/// fn answer(invocation: &CommandInvocation) -> CommandResult {
|
||||
/// CommandResult::failed(invocation, 1, "refused")
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// A struct literal does not compile, because the fields are private:
|
||||
///
|
||||
/// ```compile_fail,E0451
|
||||
/// use thing_contract::{CommandResult, Outcome, FailedOutcome};
|
||||
/// let _ = CommandResult {
|
||||
/// invocation_id: String::new(),
|
||||
/// seq: 1,
|
||||
/// outcome: Outcome::Failed(FailedOutcome { reason: String::new() }),
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// Neither does assigning the outcome:
|
||||
///
|
||||
/// ```compile_fail,E0616
|
||||
/// use thing_contract::{CommandInvocation, CommandResult, Outcome, FailedOutcome};
|
||||
/// fn tamper(invocation: &CommandInvocation) {
|
||||
/// let mut result = CommandResult::failed(invocation, 1, "refused");
|
||||
/// result.outcome = Outcome::Failed(FailedOutcome { reason: String::new() });
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Nothing converts a map into a result:
|
||||
///
|
||||
/// ```compile_fail,E0277
|
||||
/// use std::collections::BTreeMap;
|
||||
/// use thing_contract::CommandResult;
|
||||
/// let flat: BTreeMap<String, String> = BTreeMap::new();
|
||||
/// let _ = CommandResult::from(flat);
|
||||
/// ```
|
||||
///
|
||||
/// Nor a string state:
|
||||
///
|
||||
/// ```compile_fail,E0277
|
||||
/// use thing_contract::CommandResult;
|
||||
/// let _ = CommandResult::from("completed");
|
||||
/// ```
|
||||
#[derive(Clone, Debug, PartialEq, DatabaseEntry)]
|
||||
#[cultcache(type = "gamecult.thing.command_result", schema = "gamecult.thing.command_result.v1")]
|
||||
pub struct CommandResult {
|
||||
#[cultcache(key = 0)]
|
||||
invocation_id: String,
|
||||
#[cultcache(key = 1)]
|
||||
seq: i32,
|
||||
#[cultcache(key = 2)]
|
||||
outcome: Outcome,
|
||||
}
|
||||
|
||||
impl CommandResult {
|
||||
fn answering(invocation: &CommandInvocation, seq: i32, outcome: Outcome) -> Self {
|
||||
Self { invocation_id: invocation.invocation_id.clone(), seq, outcome }
|
||||
}
|
||||
|
||||
pub fn pending(invocation: &CommandInvocation, seq: i32, message: impl Into<String>) -> Self {
|
||||
Self::answering(invocation, seq, Outcome::Pending(PendingOutcome { message: message.into() }))
|
||||
}
|
||||
|
||||
pub fn completed(
|
||||
invocation: &CommandInvocation,
|
||||
seq: i32,
|
||||
source_version: Option<i64>,
|
||||
clear_drafts: bool,
|
||||
effect: Option<Effect>,
|
||||
) -> Self {
|
||||
Self::answering(
|
||||
invocation,
|
||||
seq,
|
||||
Outcome::Completed(CompletedOutcome { source_version, clear_drafts, effect }),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn denied(
|
||||
invocation: &CommandInvocation,
|
||||
seq: i32,
|
||||
reason: impl Into<String>,
|
||||
node: Option<NodeId>,
|
||||
) -> Self {
|
||||
Self::answering(invocation, seq, Outcome::Denied(DeniedOutcome { reason: reason.into(), node }))
|
||||
}
|
||||
|
||||
pub fn failed(invocation: &CommandInvocation, seq: i32, reason: impl Into<String>) -> Self {
|
||||
Self::answering(invocation, seq, Outcome::Failed(FailedOutcome { reason: reason.into() }))
|
||||
}
|
||||
|
||||
pub fn invocation_id(&self) -> &str {
|
||||
&self.invocation_id
|
||||
}
|
||||
|
||||
pub fn seq(&self) -> i32 {
|
||||
self.seq
|
||||
}
|
||||
|
||||
pub fn outcome(&self) -> &Outcome {
|
||||
&self.outcome
|
||||
}
|
||||
|
||||
pub fn record_key(&self) -> String {
|
||||
result_key(&self.invocation_id, self.seq)
|
||||
}
|
||||
}
|
||||
169
crates/thing-contract/src/source.rs
Normal file
169
crates/thing-contract/src/source.rs
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
//! Where a value comes from: a literal, a binding to a state record, or a composition parameter.
|
||||
//! A member path is a list of names and indices, never an expression.
|
||||
|
||||
use cultcache_rs::{CultSlots, CultUnion};
|
||||
|
||||
use crate::keys::{ProviderId, RecordKey, SchemaId};
|
||||
|
||||
/// A composition parameter, named.
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct ParamName {
|
||||
#[cultcache(key = 0)]
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct TextLiteral {
|
||||
#[cultcache(key = 0)]
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct NumberLiteral {
|
||||
#[cultcache(key = 0)]
|
||||
pub value: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct BoolLiteral {
|
||||
#[cultcache(key = 0)]
|
||||
pub value: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum TextSource {
|
||||
#[cultcache(key = 0)]
|
||||
Literal(TextLiteral),
|
||||
#[cultcache(key = 1)]
|
||||
Bound(Bind),
|
||||
#[cultcache(key = 2)]
|
||||
Param(ParamName),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum NumberSource {
|
||||
#[cultcache(key = 0)]
|
||||
Literal(NumberLiteral),
|
||||
#[cultcache(key = 1)]
|
||||
Bound(Bind),
|
||||
#[cultcache(key = 2)]
|
||||
Param(ParamName),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum BoolSource {
|
||||
#[cultcache(key = 0)]
|
||||
Literal(BoolLiteral),
|
||||
#[cultcache(key = 1)]
|
||||
Bound(Bind),
|
||||
#[cultcache(key = 2)]
|
||||
Param(ParamName),
|
||||
}
|
||||
|
||||
/// One member of a record, read through a path, optionally formatted.
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct Bind {
|
||||
#[cultcache(key = 0)]
|
||||
pub source: StateSource,
|
||||
#[cultcache(key = 1)]
|
||||
pub member: MemberPath,
|
||||
#[cultcache(key = 2)]
|
||||
pub format: Option<Format>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum StateSource {
|
||||
#[cultcache(key = 0)]
|
||||
Record(StateRef),
|
||||
/// The current item inside a `Repeat` template.
|
||||
#[cultcache(key = 1)]
|
||||
Item,
|
||||
}
|
||||
|
||||
/// A state record. An absent provider is the publisher of the document.
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct StateRef {
|
||||
#[cultcache(key = 0)]
|
||||
pub provider: Option<ProviderId>,
|
||||
#[cultcache(key = 1)]
|
||||
pub schema: SchemaId,
|
||||
#[cultcache(key = 2)]
|
||||
pub key: RecordKey,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct MemberPath {
|
||||
#[cultcache(key = 0)]
|
||||
pub steps: Vec<MemberStep>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum MemberStep {
|
||||
#[cultcache(key = 0)]
|
||||
Name(MemberName),
|
||||
#[cultcache(key = 1)]
|
||||
Index(MemberIndex),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct MemberName {
|
||||
#[cultcache(key = 0)]
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct MemberIndex {
|
||||
#[cultcache(key = 0)]
|
||||
pub index: i32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum Format {
|
||||
#[cultcache(key = 0)]
|
||||
Number(NumberFormat),
|
||||
#[cultcache(key = 1)]
|
||||
Duration,
|
||||
#[cultcache(key = 2)]
|
||||
Timestamp,
|
||||
#[cultcache(key = 3)]
|
||||
Affix(AffixFormat),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct NumberFormat {
|
||||
#[cultcache(key = 0)]
|
||||
pub precision: i32,
|
||||
#[cultcache(key = 1)]
|
||||
pub percent: bool,
|
||||
#[cultcache(key = 2)]
|
||||
pub unit: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct AffixFormat {
|
||||
#[cultcache(key = 0)]
|
||||
pub prefix: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub suffix: String,
|
||||
}
|
||||
|
||||
/// The records of one type, or a list member of one record.
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum CollectionSource {
|
||||
#[cultcache(key = 0)]
|
||||
Records(RecordsSource),
|
||||
#[cultcache(key = 1)]
|
||||
Member(Bind),
|
||||
#[cultcache(key = 2)]
|
||||
Param(ParamName),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct RecordsSource {
|
||||
#[cultcache(key = 0)]
|
||||
pub provider: Option<ProviderId>,
|
||||
#[cultcache(key = 1)]
|
||||
pub schema: SchemaId,
|
||||
#[cultcache(key = 2)]
|
||||
pub key_prefix: String,
|
||||
}
|
||||
241
crates/thing-contract/src/style.rs
Normal file
241
crates/thing-contract/src/style.rs
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
//! Box layout and paint as plain data. The crate holds no layout engine: core maps `BoxStyle`
|
||||
//! onto its solver.
|
||||
|
||||
use cultcache_rs::{CultSlots, CultUnion};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct Scalar {
|
||||
#[cultcache(key = 0)]
|
||||
pub value: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum Dimension {
|
||||
#[cultcache(key = 0)]
|
||||
Px(Scalar),
|
||||
#[cultcache(key = 1)]
|
||||
Percent(Scalar),
|
||||
#[cultcache(key = 2)]
|
||||
Fr(Scalar),
|
||||
#[cultcache(key = 3)]
|
||||
Auto,
|
||||
#[cultcache(key = 4)]
|
||||
Content,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct Size2 {
|
||||
#[cultcache(key = 0)]
|
||||
pub width: Dimension,
|
||||
#[cultcache(key = 1)]
|
||||
pub height: Dimension,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct Edges {
|
||||
#[cultcache(key = 0)]
|
||||
pub top: Dimension,
|
||||
#[cultcache(key = 1)]
|
||||
pub right: Dimension,
|
||||
#[cultcache(key = 2)]
|
||||
pub bottom: Dimension,
|
||||
#[cultcache(key = 3)]
|
||||
pub left: Dimension,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum Display {
|
||||
#[cultcache(key = 0)]
|
||||
Flex,
|
||||
#[cultcache(key = 1)]
|
||||
Grid,
|
||||
#[cultcache(key = 2)]
|
||||
Block,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum Direction {
|
||||
#[cultcache(key = 0)]
|
||||
Row,
|
||||
#[cultcache(key = 1)]
|
||||
Column,
|
||||
#[cultcache(key = 2)]
|
||||
RowReverse,
|
||||
#[cultcache(key = 3)]
|
||||
ColumnReverse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum Wrap {
|
||||
#[cultcache(key = 0)]
|
||||
NoWrap,
|
||||
#[cultcache(key = 1)]
|
||||
Wrap,
|
||||
#[cultcache(key = 2)]
|
||||
WrapReverse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum Position {
|
||||
#[cultcache(key = 0)]
|
||||
Relative,
|
||||
#[cultcache(key = 1)]
|
||||
Absolute,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum Overflow {
|
||||
#[cultcache(key = 0)]
|
||||
Visible,
|
||||
#[cultcache(key = 1)]
|
||||
Clip,
|
||||
#[cultcache(key = 2)]
|
||||
Scroll,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum ItemAlign {
|
||||
#[cultcache(key = 0)]
|
||||
Auto,
|
||||
#[cultcache(key = 1)]
|
||||
Start,
|
||||
#[cultcache(key = 2)]
|
||||
End,
|
||||
#[cultcache(key = 3)]
|
||||
Center,
|
||||
#[cultcache(key = 4)]
|
||||
Stretch,
|
||||
#[cultcache(key = 5)]
|
||||
Baseline,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum ContentAlign {
|
||||
#[cultcache(key = 0)]
|
||||
Auto,
|
||||
#[cultcache(key = 1)]
|
||||
Start,
|
||||
#[cultcache(key = 2)]
|
||||
End,
|
||||
#[cultcache(key = 3)]
|
||||
Center,
|
||||
#[cultcache(key = 4)]
|
||||
Stretch,
|
||||
#[cultcache(key = 5)]
|
||||
SpaceBetween,
|
||||
#[cultcache(key = 6)]
|
||||
SpaceAround,
|
||||
#[cultcache(key = 7)]
|
||||
SpaceEvenly,
|
||||
}
|
||||
|
||||
/// The layout of a box. `gap` is the column gap in `width` and the row gap in `height`.
|
||||
/// `grid_columns` and `grid_rows` are the grid tracks and are read only when `display` is Grid.
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct BoxStyle {
|
||||
#[cultcache(key = 0)]
|
||||
pub display: Display,
|
||||
#[cultcache(key = 1)]
|
||||
pub direction: Direction,
|
||||
#[cultcache(key = 2)]
|
||||
pub wrap: Wrap,
|
||||
#[cultcache(key = 3)]
|
||||
pub gap: Size2,
|
||||
#[cultcache(key = 4)]
|
||||
pub padding: Edges,
|
||||
#[cultcache(key = 5)]
|
||||
pub margin: Edges,
|
||||
#[cultcache(key = 6)]
|
||||
pub size: Size2,
|
||||
#[cultcache(key = 7)]
|
||||
pub min_size: Size2,
|
||||
#[cultcache(key = 8)]
|
||||
pub max_size: Size2,
|
||||
#[cultcache(key = 9)]
|
||||
pub position: Position,
|
||||
#[cultcache(key = 10)]
|
||||
pub inset: Edges,
|
||||
#[cultcache(key = 11)]
|
||||
pub overflow: Overflow,
|
||||
#[cultcache(key = 12)]
|
||||
pub align_items: ItemAlign,
|
||||
#[cultcache(key = 13)]
|
||||
pub align_self: ItemAlign,
|
||||
#[cultcache(key = 14)]
|
||||
pub align_content: ContentAlign,
|
||||
#[cultcache(key = 15)]
|
||||
pub justify_content: ContentAlign,
|
||||
#[cultcache(key = 16)]
|
||||
pub grow: f64,
|
||||
#[cultcache(key = 17)]
|
||||
pub shrink: f64,
|
||||
#[cultcache(key = 18)]
|
||||
pub basis: Dimension,
|
||||
#[cultcache(key = 19)]
|
||||
pub grid_columns: Vec<Dimension>,
|
||||
#[cultcache(key = 20)]
|
||||
pub grid_rows: Vec<Dimension>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct ThemeToken {
|
||||
#[cultcache(key = 0)]
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct Rgba {
|
||||
#[cultcache(key = 0)]
|
||||
pub r: u8,
|
||||
#[cultcache(key = 1)]
|
||||
pub g: u8,
|
||||
#[cultcache(key = 2)]
|
||||
pub b: u8,
|
||||
#[cultcache(key = 3)]
|
||||
pub a: u8,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum ColorRef {
|
||||
#[cultcache(key = 0)]
|
||||
Token(ThemeToken),
|
||||
#[cultcache(key = 1)]
|
||||
Rgba(Rgba),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct Border {
|
||||
#[cultcache(key = 0)]
|
||||
pub color: ColorRef,
|
||||
#[cultcache(key = 1)]
|
||||
pub width: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, CultSlots)]
|
||||
pub struct Paint {
|
||||
#[cultcache(key = 0)]
|
||||
pub background: Option<ColorRef>,
|
||||
#[cultcache(key = 1)]
|
||||
pub border: Option<Border>,
|
||||
#[cultcache(key = 2)]
|
||||
pub radius: f64,
|
||||
}
|
||||
|
||||
/// The accessibility role of a box. The accessibility tree itself is core's.
|
||||
#[derive(Clone, Debug, PartialEq, CultUnion)]
|
||||
pub enum Role {
|
||||
#[cultcache(key = 0)]
|
||||
Group,
|
||||
#[cultcache(key = 1)]
|
||||
Region,
|
||||
#[cultcache(key = 2)]
|
||||
List,
|
||||
#[cultcache(key = 3)]
|
||||
ListItem,
|
||||
#[cultcache(key = 4)]
|
||||
Heading,
|
||||
#[cultcache(key = 5)]
|
||||
Dialog,
|
||||
#[cultcache(key = 6)]
|
||||
Toolbar,
|
||||
}
|
||||
Loading…
Reference in a new issue