diff --git a/Cargo.lock b/Cargo.lock index 12d872b..4c0aadf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,25 +54,15 @@ dependencies = [ [[package]] name = "ahash" -version = "0.7.6" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", "getrandom", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -125,9 +115,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", @@ -172,9 +162,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.4" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "base64ct" @@ -199,9 +189,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" dependencies = [ "serde", ] @@ -232,9 +222,9 @@ checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytecount" -version = "0.6.4" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad152d03a2c813c80bb94fedbf3a3f02b28f793e39e7c214c8a0bcc196343de7" +checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" [[package]] name = "byteorder" @@ -344,9 +334,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -362,9 +352,9 @@ dependencies = [ [[package]] name = "crc-catalog" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crossbeam-channel" @@ -466,9 +456,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", +] [[package]] name = "digest" @@ -640,9 +633,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -650,15 +643,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -678,15 +671,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", @@ -695,21 +688,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-core", "futures-io", @@ -775,6 +768,24 @@ dependencies = [ ] [[package]] +name = "giterated-backend" +version = "0.1.0" +dependencies = [ + "anyhow", + "giterated-models", + "giterated-plugin", + "giterated-plugin-sys", + "serde", + "serde_json", + "sqlx", + "thiserror", + "tokio", + "toml", + "tracing", + "tracing-subscriber", +] + +[[package]] name = "giterated-cache" version = "0.1.0" dependencies = [ @@ -800,16 +811,14 @@ dependencies = [ "anyhow", "argon2", "async-trait", - "base64 0.21.4", + "base64 0.21.5", "bincode", "chrono", "deadpool", "futures-util", "git2", - "giterated-cache", "giterated-models", - "giterated-protocol", - "giterated-stack", + "giterated-plugin", "jsonwebtoken", "log", "rand", @@ -838,9 +847,13 @@ dependencies = [ "giterated-plugin", "giterated-plugin-sys", "serde", + "serde_json", "sqlx", "thiserror", "tokio", + "toml", + "tracing", + "tracing-subscriber", ] [[package]] @@ -849,7 +862,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", - "base64 0.21.4", + "base64 0.21.5", "bincode", "chrono", "git2", @@ -893,10 +906,13 @@ dependencies = [ name = "giterated-protocol" version = "0.1.0" dependencies = [ + "anyhow", "async-trait", "bincode", "futures-util", - "giterated-stack", + "giterated-models", + "giterated-plugin", + "giterated-plugin-sys", "rand", "rsa", "serde", @@ -904,7 +920,9 @@ dependencies = [ "thiserror", "tokio", "tokio-tungstenite", + "toml", "tracing", + "tracing-subscriber", ] [[package]] @@ -953,17 +971,14 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.6", -] [[package]] name = "hashbrown" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" dependencies = [ - "ahash 0.8.3", + "ahash", "allocator-api2", ] @@ -973,7 +988,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.1", + "hashbrown 0.14.2", ] [[package]] @@ -1075,7 +1090,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -1097,16 +1112,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -1140,12 +1155,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.1", + "hashbrown 0.14.2", ] [[package]] @@ -1159,9 +1174,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "itertools" @@ -1189,9 +1204,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" dependencies = [ "wasm-bindgen", ] @@ -1202,7 +1217,7 @@ version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "pem", "ring", "serde", @@ -1221,9 +1236,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libgit2-sys" @@ -1290,9 +1305,9 @@ checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -1361,9 +1376,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "wasi", @@ -1524,11 +1539,11 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.57" +version = "0.10.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "cfg-if", "foreign-types", "libc", @@ -1556,9 +1571,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.93" +version = "0.9.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" +checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" dependencies = [ "cc", "libc", @@ -1584,9 +1599,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", @@ -1688,6 +1703,12 @@ dependencies = [ ] [[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1779,9 +1800,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] @@ -1792,7 +1813,7 @@ version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -1847,16 +1868,14 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" +checksum = "86ef35bf3e7fe15a53c4ab08a998e42271eab13eb0db224126bc7bc4c4bad96d" dependencies = [ - "byteorder", "const-oid", "digest", "num-bigint-dig", "num-integer", - "num-iter", "num-traits", "pkcs1", "pkcs8", @@ -1885,11 +1904,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.18" +version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a74ee2d7c2581cd139b42447d7d9389b889bdaad3a73f1ebb16f2a3237bb19c" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", @@ -1970,18 +1989,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.188" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" dependencies = [ "proc-macro2", "quote", @@ -1990,9 +2009,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -2001,9 +2020,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ "serde", ] @@ -2114,9 +2133,9 @@ checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -2124,9 +2143,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys", @@ -2187,7 +2206,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d6753e460c998bbd4cd8c6f0ed9a64346fcca0723d6e75e52fdc351c5d2169d" dependencies = [ - "ahash 0.8.3", + "ahash", "atoi", "byteorder", "bytes", @@ -2204,7 +2223,7 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap 2.0.2", + "indexmap 2.1.0", "log", "memchr", "native-tls", @@ -2269,8 +2288,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "864b869fdf56263f4c95c45483191ea0af340f9f3e3e7b4d57a61c7c87a970db" dependencies = [ "atoi", - "base64 0.21.4", - "bitflags 2.4.0", + "base64 0.21.5", + "bitflags 2.4.1", "byteorder", "bytes", "chrono", @@ -2312,8 +2331,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb7ae0e6a97fb3ba33b23ac2671a5ce6e3cabe003f451abd5a56e7951d975624" dependencies = [ "atoi", - "base64 0.21.4", - "bitflags 2.4.0", + "base64 0.21.5", + "bitflags 2.4.1", "byteorder", "chrono", "crc", @@ -2436,9 +2455,9 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] name = "tempfile" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand", @@ -2449,18 +2468,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", @@ -2479,12 +2498,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ "deranged", "itoa", + "powerfmt", "serde", "time-core", "time-macros", @@ -2534,7 +2554,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.4", + "socket2 0.5.5", "tokio-macros", "windows-sys", ] @@ -2585,15 +2605,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", "futures-sink", "futures-util", - "hashbrown 0.12.3", + "hashbrown 0.14.2", "pin-project-lite", "tokio", "tracing", @@ -2613,9 +2633,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] @@ -2626,7 +2646,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", @@ -2641,11 +2661,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "log", "pin-project-lite", "tracing-attributes", @@ -2654,9 +2673,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", @@ -2665,9 +2684,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -2675,12 +2694,12 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] @@ -2813,9 +2832,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "uuid" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" dependencies = [ "getrandom", ] @@ -2865,9 +2884,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2875,9 +2894,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" dependencies = [ "bumpalo", "log", @@ -2890,9 +2909,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" dependencies = [ "cfg-if", "js-sys", @@ -2902,9 +2921,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2912,9 +2931,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", @@ -2925,15 +2944,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" dependencies = [ "js-sys", "wasm-bindgen", @@ -2977,10 +2996,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ "windows-targets", ] @@ -3053,9 +3072,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.16" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711d82167854aff2018dfd193aa0fef5370f456732f0d5a0c59b0f1b4b907" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" dependencies = [ "memchr", ] @@ -3071,6 +3090,26 @@ dependencies = [ ] [[package]] +name = "zerocopy" +version = "0.7.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] name = "zeroize" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml index b1a630d..d6cb209 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,9 +4,10 @@ members = [ "giterated-models", "giterated-stack", "giterated-cache", - "giterated-protocol", "giterated-plugins/giterated-plugin", "giterated-plugins/giterated-plugin-sys", "giterated-plugins/example-plugin", - "giterated-plugins/giterated-issues" + "giterated-plugins/giterated-backend", + "giterated-plugins/giterated-issues", + "giterated-plugins/giterated-protocol" ] \ No newline at end of file diff --git a/giterated-daemon/Cargo.toml b/giterated-daemon/Cargo.toml index c43a603..9dfb55a 100644 --- a/giterated-daemon/Cargo.toml +++ b/giterated-daemon/Cargo.toml @@ -30,9 +30,7 @@ argon2 = "0.5" aes-gcm = "0.10" semver = {version = "1.0", features = ["serde"]} giterated-models = { path = "../giterated-models" } -giterated-stack = { path = "../giterated-stack" } -giterated-cache = { path = "../giterated-cache" } -giterated-protocol = { path = "../giterated-protocol" } +giterated-plugin = { path = "../giterated-plugins/giterated-plugin" } deadpool = "0.9" bincode = "1.3" tokio-util = {version = "0.7", features = ["rt"]} diff --git a/giterated-daemon/src/client.rs b/giterated-daemon/src/client.rs index dccb2f3..17e9fbb 100644 --- a/giterated-daemon/src/client.rs +++ b/giterated-daemon/src/client.rs @@ -1,18 +1,20 @@ +use std::sync::Arc; + use futures_util::{SinkExt, StreamExt}; use giterated_models::{ error::{IntoInternalError, OperationError}, instance::Instance, object_backend::ObjectBackend, }; +use giterated_plugin::new_stack::Runtime; use giterated_protocol::{AuthenticatedPayload, NetworkedObject, NetworkedOperation}; -use giterated_stack::{GiteratedStack, StackOperationState}; use tokio::net::TcpStream; use tokio_tungstenite::{tungstenite::Message, WebSocketStream}; pub async fn client_wrapper( our_instance: Instance, mut socket: WebSocketStream, - runtime: GiteratedStack, + runtime: Arc, ) { loop { let message = socket.next().await; @@ -65,39 +67,40 @@ pub async fn client_wrapper( payload.operation ); - let operation_state = StackOperationState { - our_instance: our_instance.clone(), - runtime: runtime.clone(), - instance: None, - user: None, - }; + todo!() + + // let operation_state = StackOperationState { + // our_instance: our_instance.clone(), + // instance: None, + // user: None, + // }; - let result = handle_client_message(payload, operation_state, runtime.clone()).await; + // let result = handle_client_message(payload, operation_state, runtime.clone()).await; // Grab operation errors so we can log them, they don't make it across the network - if let Err(OperationError::Internal(internal_error)) = &result { - error!("An internal error has occurred:\n{:?}", internal_error); - } + // if let Err(OperationError::Internal(internal_error)) = &result { + // error!("An internal error has occurred:\n{:?}", internal_error); + // } - // Map error to the network variant - let result = result.map_err(|e| e.into_network()); + // // Map error to the network variant + // let result = result.map_err(|e| e.into_network()); - socket - .send(Message::Binary(bincode::serialize(&result).unwrap())) - .await - .expect("there was an error sending a message, this is a problem for the receiver"); + // socket + // .send(Message::Binary(bincode::serialize(&result).unwrap())) + // .await + // .expect("there was an error sending a message, this is a problem for the receiver"); } } pub async fn handle_client_message( payload: AuthenticatedPayload, - operation_state: StackOperationState, - runtime: GiteratedStack, + // operation_state: StackOperationState, + runtime: Arc, ) -> Result, OperationError>> { - let mut networked_object = runtime - .get_object::(&payload.object, &operation_state) - .await - .as_internal_error_with_context("handling client message")?; + // let mut networked_object = runtime + // .get_object::(&payload.object, &operation_state) + // .await + // .as_internal_error_with_context("handling client message")?; let message: giterated_protocol::GiteratedMessage = payload.into_message(); @@ -109,7 +112,9 @@ pub async fn handle_client_message( trace!("Calling handler for networked operation"); - networked_object - .request(networked_operation, &operation_state) - .await + // networked_object + // .request(networked_operation, &operation_state) + // .await + + todo!() } diff --git a/giterated-daemon/src/lib.rs b/giterated-daemon/src/lib.rs index 2d8d4b6..c8bf982 100644 --- a/giterated-daemon/src/lib.rs +++ b/giterated-daemon/src/lib.rs @@ -3,9 +3,7 @@ use std::str::FromStr; use semver::{Version, VersionReq}; pub mod authentication; -pub mod backend; pub mod client; -pub mod database_backend; #[macro_use] extern crate tracing; diff --git a/giterated-daemon/src/main.rs b/giterated-daemon/src/main.rs index 602261c..765d3ae 100644 --- a/giterated-daemon/src/main.rs +++ b/giterated-daemon/src/main.rs @@ -1,18 +1,10 @@ use anyhow::Error; -use giterated_cache::CacheSubstack; -use giterated_daemon::{ - authentication::AuthenticationTokenGranter, - backend::{ - git::GitBackend, settings::DatabaseSettings, user::UserAuth, RepositoryBackend, UserBackend, - }, - client::client_wrapper, - database_backend::DatabaseBackend, -}; +use giterated_daemon::{authentication::AuthenticationTokenGranter, client::client_wrapper}; use giterated_models::instance::Instance; +use giterated_plugin::new_stack::Runtime; use giterated_protocol::NetworkedSubstack; -use giterated_stack::GiteratedStackBuilder; use sqlx::{postgres::PgConnectOptions, ConnectOptions, PgPool}; use std::{net::SocketAddr, str::FromStr, sync::Arc}; use tokio::{ @@ -51,55 +43,14 @@ async fn main() -> Result<(), Error> { sqlx::migrate!().run(&db_pool).await?; info!("Connected"); - let stack_cell = Arc::new(OnceCell::default()); - - let settings = Arc::new(Mutex::new(DatabaseSettings { - pg_pool: db_pool.clone(), - stack: stack_cell.clone(), - })); - - let repository_backend: Arc> = - Arc::new(Mutex::new(GitBackend { - pg_pool: db_pool.clone(), - repository_folder: String::from( - config["giterated"]["backend"]["git"]["root"] - .as_str() - .unwrap(), - ), - instance: Instance::from_str(config["giterated"]["instance"].as_str().unwrap()) - .unwrap(), - stack: stack_cell.clone(), - })); - let token_granter = Arc::new(Mutex::new(AuthenticationTokenGranter { config: config.clone(), instance: Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(), })); - let user_backend: Arc> = Arc::new(Mutex::new(UserAuth::new( - db_pool.clone(), - &Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(), - token_granter.clone(), - settings.clone(), - ))); - info!("Connected"); - let database_backend = DatabaseBackend::new( - Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(), - user_backend.clone(), - repository_backend.clone(), - db_pool.clone(), - stack_cell.clone(), - ); - - let mut runtime = GiteratedStackBuilder::default(); - - let database_backend = database_backend.into_substack(); - runtime.merge_builder(database_backend); - - let cache_backend = CacheSubstack::default(); - runtime.merge_builder(cache_backend.into_substack()); + let mut runtime = Runtime::default(); let networked_stack = NetworkedSubstack { home_uri: Some( @@ -108,13 +59,8 @@ async fn main() -> Result<(), Error> { .0, ), }; - runtime.merge_builder(networked_stack.into_server_substack()); - - let runtime = runtime.finish(); - stack_cell - .set(runtime.clone()) - .expect("failed to store global daemon stack"); + let runtime = Arc::new(runtime); let pool = LocalPoolHandle::new(5); diff --git a/giterated-models/src/repository/mod.rs b/giterated-models/src/repository/mod.rs index 71bbc4c..24d6870 100644 --- a/giterated-models/src/repository/mod.rs +++ b/giterated-models/src/repository/mod.rs @@ -49,6 +49,16 @@ pub struct Repository { pub instance: Instance, } +impl Repository { + pub fn new(instance: Instance, owner: User, name: String) -> Self { + Self { + owner, + name, + instance, + } + } +} + impl Display for Repository { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_str(&format!("{}/{}@{}", self.owner, self.name, self.instance)) diff --git a/giterated-plugins/example-plugin/src/lib.rs b/giterated-plugins/example-plugin/src/lib.rs index b305ea8..3125afc 100644 --- a/giterated-plugins/example-plugin/src/lib.rs +++ b/giterated-plugins/example-plugin/src/lib.rs @@ -9,7 +9,7 @@ use giterated_models::{ use giterated_plugin::{ handle::PluginInitializationState, new_stack::{FFIPluginMeta, PluginState}, - HostVTable, InitializationVTable, + vtable::{HostVTable, InitializationVTable}, }; use giterated_plugin_sys::PluginStackBuilder; use tracing::{info, trace_span, Level}; @@ -62,7 +62,7 @@ pub extern "C" fn initialize_registration( let mut builder = PluginStackBuilder::new((), state, init_vtable); builder.object::().object::(); - builder.operation_handler(handler); + builder.operation(handler); builder.value(value_getter); // builder.setting_getter(setting_getter); diff --git a/giterated-plugins/giterated-backend/Cargo.toml b/giterated-plugins/giterated-backend/Cargo.toml new file mode 100644 index 0000000..5e29db7 --- /dev/null +++ b/giterated-plugins/giterated-backend/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "giterated-backend" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +giterated-plugin = { path = "../giterated-plugin" } +giterated-models = { path = "../../giterated-models" } +serde = { version = "1.0", features = [ "derive" ]} +anyhow = "1" +thiserror = "1" +sqlx = { version = "0.7", features = [ "runtime-tokio", "tls-native-tls", "postgres", "macros", "migrate", "chrono" ] } +tokio = { version = "1.32", features = [ "full" ] } +giterated-plugin-sys = { path = "../giterated-plugin-sys" } +toml = { version = "0.7" } +tracing = "0.1" +tracing-subscriber = "0.3" +serde_json = "1.0" diff --git a/giterated-plugins/giterated-backend/src/handlers.rs b/giterated-plugins/giterated-backend/src/handlers.rs new file mode 100644 index 0000000..f2b5dcc --- /dev/null +++ b/giterated-plugins/giterated-backend/src/handlers.rs @@ -0,0 +1,28 @@ +use std::sync::Arc; + +use giterated_models::{ + error::{OperationError, RepositoryError, UserError}, + repository::{Repository, RepositoryInfoRequest, RepositorySummary, RepositoryView}, + user::{User, UserRepositoriesRequest}, +}; +use giterated_plugin::new_stack::{OperationState, Runtime, State}; + +use crate::DatabaseBackend; + +pub async fn user_get_repositories( + state: DatabaseBackend, + object: User, + request: UserRepositoriesRequest, +) -> Result, OperationError> { + todo!() +} + +pub async fn repository_info( + state: DatabaseBackend, + object: Repository, + request: RepositoryInfoRequest, + runtime: Arc, + State(operation_state): State, +) -> Result> { + todo!() +} diff --git a/giterated-plugins/giterated-backend/src/lib.rs b/giterated-plugins/giterated-backend/src/lib.rs new file mode 100644 index 0000000..4f4e49b --- /dev/null +++ b/giterated-plugins/giterated-backend/src/lib.rs @@ -0,0 +1,16 @@ +pub mod handlers; +pub mod value; + +use giterated_models::{instance::Instance, repository::Repository, user::User}; +use giterated_plugin_sys::{PluginStackBuilder, ValueSettingExt}; +use handlers::{repository_info, user_get_repositories}; +use sqlx::PgPool; +use value::{user_get_bio, user_get_display_name, user_set_bio, user_set_display_name}; + +/// A backend implementation which attempts to resolve data from the instance's database. +#[derive(Debug, Clone)] +#[allow(unused)] +pub struct DatabaseBackend { + pub(self) our_instance: Instance, + pub(self) pool: PgPool, +} diff --git a/giterated-plugins/giterated-backend/src/value.rs b/giterated-plugins/giterated-backend/src/value.rs new file mode 100644 index 0000000..ea9a291 --- /dev/null +++ b/giterated-plugins/giterated-backend/src/value.rs @@ -0,0 +1,36 @@ +use giterated_models::{ + error::OperationError, + user::{Bio, DisplayName, User}, +}; + +use crate::DatabaseBackend; + +pub async fn user_get_display_name( + state: DatabaseBackend, + user: User, +) -> Result> { + todo!() +} + +pub async fn user_set_display_name( + state: DatabaseBackend, + user: User, + display_name: DisplayName, +) -> Result<(), OperationError> { + todo!() +} + +pub async fn user_get_bio( + state: DatabaseBackend, + user: User, +) -> Result> { + todo!() +} + +pub async fn user_set_bio( + state: DatabaseBackend, + user: User, + bio: Bio, +) -> Result<(), OperationError> { + todo!() +} diff --git a/giterated-plugins/giterated-issues/Cargo.toml b/giterated-plugins/giterated-issues/Cargo.toml index ea726ba..cde3056 100644 --- a/giterated-plugins/giterated-issues/Cargo.toml +++ b/giterated-plugins/giterated-issues/Cargo.toml @@ -3,6 +3,11 @@ name = "giterated-issues" version = "0.1.0" edition = "2021" +[lib] +name = "giterated_issues" +path = "src/lib.rs" +crate-type = ["rlib", "dylib"] + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] @@ -14,3 +19,7 @@ thiserror = "1" sqlx = { version = "0.7", features = [ "runtime-tokio", "tls-native-tls", "postgres", "macros", "migrate", "chrono" ] } tokio = { version = "1.32", features = [ "full" ] } giterated-plugin-sys = { path = "../giterated-plugin-sys" } +toml = { version = "0.7" } +tracing = "0.1" +tracing-subscriber = "0.3" +serde_json = "1.0" diff --git a/giterated-plugins/giterated-issues/src/lib.rs b/giterated-plugins/giterated-issues/src/lib.rs index ed01965..9e84f14 100644 --- a/giterated-plugins/giterated-issues/src/lib.rs +++ b/giterated-plugins/giterated-issues/src/lib.rs @@ -1,11 +1,15 @@ -use std::{fmt::Display, str::FromStr, sync::OnceLock}; +use std::{ + fmt::Display, + str::FromStr, + sync::{Arc, OnceLock}, +}; use anyhow::Error; use giterated_models::{object::GiteratedObject, repository::Repository}; use giterated_plugin::{ handle::PluginInitializationState, new_stack::{FFIPluginMeta, PluginState}, - HostVTable, InitializationVTable, + vtable::{HostVTable, InitializationVTable}, }; use giterated_plugin_sys::PluginStackBuilder; use handlers::{ @@ -15,7 +19,16 @@ use handlers::{ }; use serde::{Deserialize, Serialize}; use setting::{Contents, NotificationsOverride}; -use sqlx::PgPool; +use sqlx::{postgres::PgConnectOptions, PgPool}; +use tokio::{ + fs::File, + io::AsyncReadExt, + runtime::Runtime, + spawn, + task::{block_in_place, spawn_blocking}, +}; +use toml::Table; +use tracing::{debug, info}; use value::{Author, CommentCount, CreationDate, Name}; pub mod db; @@ -74,6 +87,7 @@ impl FromStr for Issue { pub struct IssueParseError; static INIT_VTABLE: OnceLock = OnceLock::new(); +static ASYNC_RUNTIME: OnceLock = OnceLock::new(); #[no_mangle] pub extern "C" fn plugin_meta() -> FFIPluginMeta { @@ -116,12 +130,39 @@ pub extern "C" fn initialize() -> PluginState { pub extern "C" fn initialize_registration( state: *mut PluginInitializationState, ) -> *mut PluginInitializationState { + let runtime = Runtime::new().unwrap(); + // let _guard: tracing::span::EnteredSpan = trace_span!("initialize_registration").entered(); let init_vtable = INIT_VTABLE.get().unwrap(); - let plugin_state = { todo!() }; + let db_pool = runtime.block_on(async { + let config: Table = { + let mut file = File::open("Giterated.toml").await.unwrap(); + let mut text = String::new(); + file.read_to_string(&mut text).await.unwrap(); + text.parse().unwrap() + }; + let db_conn_options = PgConnectOptions::new() + .host(config["postgres"]["host"].as_str().unwrap()) + .port(config["postgres"]["port"].as_integer().unwrap() as u16) + .database(config["postgres"]["database"].as_str().unwrap()) + .username(config["postgres"]["user"].as_str().unwrap()) + .password(config["postgres"]["password"].as_str().unwrap()); + let db_pool = PgPool::connect_with(db_conn_options).await.unwrap(); + + debug!("Running database migrations..."); + // sqlx::migrate!().run(&db_pool).await.unwrap(); + info!("Connected"); + + db_pool + }); + + ASYNC_RUNTIME.set(runtime).unwrap(); + + let plugin_state = IssuesPluginState { pool: db_pool }; - let mut builder = PluginStackBuilder::new(plugin_state, state, init_vtable); + let mut builder: PluginStackBuilder<'_, IssuesPluginState> = + PluginStackBuilder::new(plugin_state, state, init_vtable); builder.object::(); @@ -138,10 +179,10 @@ pub extern "C" fn initialize_registration( .value(issue_value_author); builder - .operation_handler(create_issue_request) - .operation_handler(query_issues_request) - .operation_handler(edit_issue_request) - .operation_handler(issue_post_comment_request); + .operation(create_issue_request) + .operation(query_issues_request) + .operation(edit_issue_request) + .operation(issue_post_comment_request); state } diff --git a/giterated-plugins/giterated-issues/src/main.rs b/giterated-plugins/giterated-issues/src/main.rs new file mode 100644 index 0000000..1f93aa5 --- /dev/null +++ b/giterated-plugins/giterated-issues/src/main.rs @@ -0,0 +1,45 @@ +use std::str::FromStr; + +use giterated_issues::operations::CreateIssueRequest; +use giterated_models::{ + instance::Instance, + object::{GiteratedObject, ObjectRequest}, + operation::GiteratedOperation, + repository::Repository, + user::User, +}; +use giterated_plugin::{handle::PluginHandle, new_stack::Runtime}; +use tracing::Level; + +#[tokio::main] +pub async fn main() { + tracing_subscriber::fmt() + .pretty() + .with_thread_names(true) + .with_max_level(Level::TRACE) + .init(); + + let mut handle = PluginHandle::from_dylib("giterated_issues.dll").unwrap(); + + let mut runtime = Runtime::default(); + + runtime.insert_plugin(handle); + + let operation = CreateIssueRequest { + name: String::from("test issue"), + contents: String::from("hey!"), + author: User::from_str("amber:giterated.dev").unwrap(), + }; + + match runtime.handle_typed( + Repository::from_str("barson:giterated.dev/foo@giterated.dev").unwrap(), + operation, + ) { + Ok(success) => { + println!("Success in create issue: {:?}", success) + } + Err(err) => { + println!("Error in create issue: {:?}", err) + } + } +} diff --git a/giterated-plugins/giterated-plugin-sys/src/lib.rs b/giterated-plugins/giterated-plugin-sys/src/lib.rs index 436daa0..d077640 100644 --- a/giterated-plugins/giterated-plugin-sys/src/lib.rs +++ b/giterated-plugins/giterated-plugin-sys/src/lib.rs @@ -6,13 +6,17 @@ use giterated_models::{ }; use giterated_plugin::{ callback::{ - IntoPluginOperationHandler, IntoPluginSettingGetter, IntoPluginSettingSetter, + CallbackPtr, IntoPluginOperationHandler, IntoPluginSettingGetter, IntoPluginSettingSetter, IntoPluginValueGetter, OperationHandlerCallback, SettingGetterCallback, ValueGetterCallback, }, handle::PluginInitializationState, - InitializationVTable, IntoObjectVTable, IntoOperationVTable, IntoSettingVTable, - IntoValueVTable, ObjectVtable, OperationVTable, SettingVtable, ValueVTable, + new_stack::PluginState, + vtable::{ + InitializationVTable, IntoObjectVTable, IntoOperationVTable, IntoSettingVTable, + IntoValueVTable, ObjectVtable, OperationVTable, SettingVtable, ValueVTable, + }, + AnyObject, NewAnyValue, }; use tracing::trace_span; @@ -45,7 +49,7 @@ impl<'init, S> PluginStackBuilder<'init, S> { self } - pub fn operation(&mut self) -> &mut Self + pub fn register_operation(&mut self) -> &mut Self where D: IntoOperationVTable + GiteratedOperation, O: GiteratedObject, @@ -133,12 +137,13 @@ impl<'init, S> PluginStackBuilder<'init, S> { self } - pub fn operation_handler< + pub fn operation< DS, DF, + A, O: GiteratedObject + IntoObjectVTable, D: IntoOperationVTable + GiteratedOperation, - T: IntoPluginOperationHandler, + T: IntoPluginOperationHandler, >( &mut self, handler: T, @@ -150,14 +155,14 @@ impl<'init, S> PluginStackBuilder<'init, S> { self.init_state, O::object_name(), D::operation_name(), - OperationHandlerCallback::new::(handler), + OperationHandlerCallback::new::(handler), ) } // TODO: Yikes? self.object::(); - self.operation::(); + self.register_operation::(); self } @@ -209,3 +214,57 @@ impl<'init, S> PluginStackBuilder<'init, S> { // self // } } + +pub trait ValueSettingExt { + fn value_setting(&mut self, get: HG, set: HS) -> &mut Self + where + O: GiteratedObject + IntoObjectVTable + 'static, + VS: GiteratedObjectValue + IntoValueVTable + Setting + IntoSettingVTable, + HG: IntoPluginSettingGetter, + HS: IntoPluginSettingSetter; +} + +impl ValueSettingExt for PluginStackBuilder<'_, PS> { + fn value_setting(&mut self, get: HG, set: HS) -> &mut Self + where + O: GiteratedObject + IntoObjectVTable + 'static, + VS: GiteratedObjectValue + IntoValueVTable + Setting + IntoSettingVTable, + HG: IntoPluginSettingGetter, + HS: IntoPluginSettingSetter, + { + self + } +} + +pub trait ValueSettingGetter { + unsafe extern "C" fn get_value( + callback: CallbackPtr, + state: &PluginState, + object: AnyObject, + ) -> Result; + + fn callback_ptr(&self) -> CallbackPtr; +} + +impl ValueSettingGetter for HG +where + O: GiteratedObject, + VS: GiteratedObjectValue, + HG: IntoPluginSettingGetter, +{ + unsafe extern "C" fn get_value( + callback: CallbackPtr, + state: &PluginState, + object: AnyObject, + ) -> Result { + let result = HG::get_setting(callback, state, object)?; + + let setting = *result.transmute_owned::(); + + Ok(NewAnyValue::new(setting)) + } + + fn callback_ptr(&self) -> CallbackPtr { + self.callback_ptr() + } +} diff --git a/giterated-plugins/giterated-plugin/src/callback/mod.rs b/giterated-plugins/giterated-plugin/src/callback/mod.rs index 34afa9e..52cea79 100644 --- a/giterated-plugins/giterated-plugin/src/callback/mod.rs +++ b/giterated-plugins/giterated-plugin/src/callback/mod.rs @@ -1,10 +1,14 @@ mod operation; +use std::sync::Arc; + pub use operation::*; mod value; pub use value::*; mod setting; pub use setting::*; +use crate::new_stack::{PluginState, Runtime}; + /// A container for a callback pointer, used to provide an internal callback function or /// state to a plugin when performing a callback. #[derive(Clone, Copy)] @@ -16,3 +20,9 @@ impl CallbackPtr { Self(callback) } } + +#[repr(C)] +pub struct RuntimeState { + pub runtime: Arc, + pub operation_state: PluginState, +} diff --git a/giterated-plugins/giterated-plugin/src/callback/operation.rs b/giterated-plugins/giterated-plugin/src/callback/operation.rs index 81265f6..dc0b07a 100644 --- a/giterated-plugins/giterated-plugin/src/callback/operation.rs +++ b/giterated-plugins/giterated-plugin/src/callback/operation.rs @@ -1,20 +1,28 @@ use giterated_models::error::OperationError; -use crate::{new_stack::PluginState, AnyObject, AnyOperation}; +use crate::{ + new_stack::{PluginState, Runtime, State}, + AnyObject, AnyOperation, +}; -use std::{any::type_name, fmt::Debug, future::Future}; +use std::{any::type_name, fmt::Debug, future::Future, sync::Arc}; -use super::CallbackPtr; +use super::{CallbackPtr, RuntimeState}; #[derive(Clone, Copy)] pub struct OperationHandlerCallback { pub callback_ptr: CallbackPtr, - pub func: - unsafe extern "C" fn(CallbackPtr, &PluginState, object: AnyObject, operation: AnyOperation), + pub func: unsafe extern "C" fn( + CallbackPtr, + &RuntimeState, + &PluginState, + object: AnyObject, + operation: AnyOperation, + ), } impl OperationHandlerCallback { - pub fn new>( + pub fn new>( handler: T, ) -> Self { OperationHandlerCallback { @@ -24,9 +32,10 @@ impl OperationHandlerCallback { } } -pub trait IntoPluginOperationHandler { +pub trait IntoPluginOperationHandler { unsafe extern "C" fn handle( callback_ptr: CallbackPtr, + runtime_state: &RuntimeState, state: &PluginState, object: AnyObject, operation: AnyOperation, @@ -34,7 +43,7 @@ pub trait IntoPluginOperationHandler { fn callback_ptr(&self) -> CallbackPtr; } -impl IntoPluginOperationHandler for F +impl IntoPluginOperationHandler for F where Fut: Future>>, F: Fn(S, O, D) -> Fut, @@ -44,6 +53,7 @@ where { unsafe extern "C" fn handle( callback: CallbackPtr, + runtime_state: &RuntimeState, state: &PluginState, mut object: AnyObject, mut operation: AnyOperation, @@ -73,3 +83,94 @@ where unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } } } + +impl IntoPluginOperationHandler for F +where + Fut: Future>>, + F: Fn(S, O, D, A1) -> Fut, + S: Clone + Debug, + O: Debug, + D: Debug, +{ + unsafe extern "C" fn handle( + callback_ptr: CallbackPtr, + runtime_state: &RuntimeState, + state: &PluginState, + object: AnyObject, + operation: AnyOperation, + ) { + todo!() + } + + fn callback_ptr(&self) -> CallbackPtr { + todo!() + } +} + +impl IntoPluginOperationHandler for F +where + Fut: Future>>, + F: Fn(S, O, D, A1, A2) -> Fut, + S: Clone + Debug, + O: Debug, + D: Debug, +{ + unsafe extern "C" fn handle( + callback_ptr: CallbackPtr, + runtime_state: &RuntimeState, + state: &PluginState, + object: AnyObject, + operation: AnyOperation, + ) { + todo!() + } + + fn callback_ptr(&self) -> CallbackPtr { + todo!() + } +} + +pub trait FromOperationState: Sized { + fn from_operation_state( + state: &S, + runtime_state: &RuntimeState, + object: &O, + operation: &D, + ) -> Result>; +} + +impl FromOperationState for Arc { + fn from_operation_state( + state: &S, + runtime_state: &RuntimeState, + object: &O, + operation: &D, + ) -> Result> { + Ok(runtime_state.runtime.clone()) + } +} + +impl FromOperationState for Option +where + T: FromOperationState, +{ + fn from_operation_state( + state: &S, + runtime_state: &RuntimeState, + object: &O, + operation: &D, + ) -> Result> { + Ok(T::from_operation_state(state, runtime_state, object, operation).ok()) + } +} + +impl FromOperationState for State { + fn from_operation_state( + state: &S, + runtime_state: &RuntimeState, + object: &O, + operation: &D, + ) -> Result> { + Ok(unsafe { State(runtime_state.operation_state.transmute_ref::().clone()) }) + } +} diff --git a/giterated-plugins/giterated-plugin/src/callback/value.rs b/giterated-plugins/giterated-plugin/src/callback/value.rs index d61217b..654ed3d 100644 --- a/giterated-plugins/giterated-plugin/src/callback/value.rs +++ b/giterated-plugins/giterated-plugin/src/callback/value.rs @@ -1,10 +1,13 @@ use std::future::Future; use giterated_models::{ - error::OperationError, object::GiteratedObject, value::GiteratedObjectValue, + error::OperationError, object::GiteratedObject, settings::Setting, value::GiteratedObjectValue, }; -use crate::{new_stack::PluginState, AnyObject, NewAnyValue}; +use crate::{ + new_stack::PluginState, + vtable::{AnyObject, NewAnyValue}, +}; use super::CallbackPtr; diff --git a/giterated-plugins/giterated-plugin/src/handle.rs b/giterated-plugins/giterated-plugin/src/handle.rs index 7b9c547..f262422 100644 --- a/giterated-plugins/giterated-plugin/src/handle.rs +++ b/giterated-plugins/giterated-plugin/src/handle.rs @@ -11,8 +11,8 @@ use crate::{ ObjectOperationPair, ObjectSettingPair, ObjectValuePair, PluginMeta, PluginState, RuntimeHandlers, TypeMetadata, }, - FFISettingMeta, FFIValueChangeHandler, FFIValueMeta, GiteratedPluginApi, InitializationVTable, - ObjectVtable, OperationVTable, SettingVtable, ValueVTable, + vtable::{InitializationVTable, ObjectVtable, OperationVTable, SettingVtable, ValueVTable}, + GiteratedPluginApi, }; #[derive(Clone)] @@ -23,6 +23,9 @@ pub struct PluginHandle { pub state: PluginState, } +unsafe impl Send for PluginHandle {} +unsafe impl Sync for PluginHandle {} + impl PluginHandle { pub fn from_dylib(path: &str) -> Result { let mut handle = unsafe { Container::load(path) }?; @@ -132,7 +135,6 @@ pub struct PluginInitializationTable<'a> { impl<'a> PluginInitializationTable<'a> { pub unsafe fn func_table(&mut self) -> InitializationVTable { InitializationVTable { - register_value_change, register_object, register_operation, register_setting, @@ -144,15 +146,6 @@ impl<'a> PluginInitializationTable<'a> { } } -unsafe extern "C" fn register_value_change( - state: *mut PluginInitializationState, - object_kind: &str, - value_name: &str, - vtable: FFIValueChangeHandler, -) { - todo!() -} - unsafe extern "C" fn register_object( state: *mut PluginInitializationState, object_kind: &'static str, diff --git a/giterated-plugins/giterated-plugin/src/lib.rs b/giterated-plugins/giterated-plugin/src/lib.rs index 393359d..fdc606a 100644 --- a/giterated-plugins/giterated-plugin/src/lib.rs +++ b/giterated-plugins/giterated-plugin/src/lib.rs @@ -17,6 +17,9 @@ use giterated_models::{ use handle::PluginInitializationState; use new_stack::{FFIPluginMeta, PluginState}; +pub use vtable::{AnyFailure, AnyObject, AnyOperation, AnySuccess, NewAnySetting, NewAnyValue}; +use vtable::{HostVTable, InitializationVTable}; + #[derive(WrapperApi)] pub struct GiteratedPluginApi { plugin_meta: unsafe extern "C" fn() -> FFIPluginMeta, @@ -41,384 +44,16 @@ impl FFIBox { } } -#[repr(C)] -pub struct FFIObject(&'static str); - -#[repr(C)] -struct FFIOperationHandler( - for<'a> unsafe extern "C" fn(operation: FFIOperation<'a>) -> Result, FFIBox<[u8]>>, -); - -#[repr(C)] -struct FFIOperation<'a> { - operation_name: &'a str, - object_name: &'a str, - object: FFIObject, - operation: &'a [u8], -} - -#[derive(Clone, Copy)] -#[repr(C)] -pub struct OperationVTable { - pub serialize: unsafe extern "C" fn(AnyObject) -> Result, ()>, - pub deserialize: unsafe extern "C" fn(&[u8]) -> Result, - pub is_same: unsafe extern "C" fn(AnyObject) -> bool, - pub serialize_success: unsafe extern "C" fn(()) -> Result, ()>, - pub serialize_failure: unsafe extern "C" fn(()) -> Result, ()>, - pub deserialize_success: unsafe extern "C" fn(&[u8]) -> Result<(), ()>, - pub deserialize_failure: unsafe extern "C" fn(&[u8]) -> Result<(), ()>, -} - -impl OperationVTable { - pub fn new>() -> Self { - Self { - serialize: T::serialize, - deserialize: T::deserialize, - is_same: T::is_same, - serialize_success: T::serialize_success, - serialize_failure: T::serialize_failure, - deserialize_success: T::deserialize_success, - deserialize_failure: T::deserialize_failure, - } - } -} - -pub struct AnyOperation { - /// A pointer to the plugin-local object type. We are not capable of - /// knowing what this type is, we use the provided vtable. - inner: FFIBox<()>, - vtable: OperationVTable, -} - -impl AnyOperation { - pub unsafe fn transmute_owned(&mut self) -> Box { - Box::from_raw(self.inner.0 as *mut T) - } - - pub unsafe fn transmute_ref(&self) -> &T { - let ptr: *const T = transmute(self.inner.0); - - ptr.as_ref().unwrap() - } -} - -#[repr(C)] -pub struct FFIValueChangeHandler(); - -#[derive(Clone, Copy)] -#[repr(C)] -pub struct ObjectVtable { - pub to_str: unsafe extern "C" fn(AnyObject) -> FFIBox, - pub from_str: unsafe extern "C" fn(&str) -> Result>, - pub home_uri: unsafe extern "C" fn(AnyObject) -> FFIBox, - pub is_same: unsafe extern "C" fn(AnyObject) -> bool, -} - -impl ObjectVtable { - pub const fn new() -> Self { - Self { - to_str: T::to_str, - from_str: T::from_str, - home_uri: T::home_uri, - is_same: T::is_same, - } - } -} - -#[repr(C)] -pub struct NewAnySetting { - /// A pointer to the plugin-local object type. We are not capable of - /// knowing what this type is, we use the provided vtable. - inner: FFIBox<()>, - vtable: SettingVtable, -} - -impl NewAnySetting { - pub fn new(value: V) -> Self { - Self { - inner: FFIBox::from_box(Box::new(value)).untyped(), - vtable: SettingVtable::new::(), - } - } -} - -#[derive(Clone, Copy)] -#[repr(C)] -pub struct SettingVtable { - pub deserialize: unsafe extern "C" fn(&[u8]) -> Result<(), ()>, - pub serialize: unsafe extern "C" fn(NewAnySetting) -> Result, ()>, -} - -impl SettingVtable { - pub fn new() -> Self { - Self { - deserialize: T::deserialize, - serialize: T::serialize, - } - } -} - -#[repr(C)] -pub struct NewAnyValue { - /// A pointer to the plugin-local object type. We are not capable of - /// knowing what this type is, we use the provided vtable. - inner: FFIBox<()>, - vtable: ValueVTable, -} - -impl NewAnyValue { - pub fn new>(value: V) -> Self { - NewAnyValue { - inner: FFIBox::from_box(Box::new(value)).untyped(), - vtable: ValueVTable::new::(), - } - } -} - -#[derive(Clone, Copy)] -#[repr(C)] -pub struct ValueVTable { - pub deserialize: unsafe extern "C" fn(&[u8]) -> Result, - pub serialize: unsafe extern "C" fn(NewAnyValue) -> Result, ()>, -} - -impl ValueVTable { - pub fn new>() -> Self { - Self { - deserialize: T::deserialize, - serialize: T::serialize, - } - } -} - -pub trait IntoObjectVTable { - unsafe extern "C" fn to_str(this: AnyObject) -> FFIBox; - unsafe extern "C" fn from_str(src: &str) -> Result>; - unsafe extern "C" fn home_uri(this: AnyObject) -> FFIBox; - unsafe extern "C" fn is_same(other: AnyObject) -> bool; -} - -impl IntoObjectVTable for T { - unsafe extern "C" fn to_str(mut this: AnyObject) -> FFIBox { - let this: &Box = this.transmute_ref(); - - let result = this.to_string(); - - FFIBox::from_box(result.into_boxed_str()) - } - - unsafe extern "C" fn from_str(src: &str) -> Result> { - let result = T::from_object_str(src).unwrap(); - - let any_object = AnyObject::new(result); - - Ok(any_object) - } - - unsafe extern "C" fn home_uri(this: AnyObject) -> FFIBox { - todo!() - } - - unsafe extern "C" fn is_same(other: AnyObject) -> bool { +impl AsRef for FFIBox { + fn as_ref(&self) -> &T { todo!() } } -pub trait IntoOperationVTable { - unsafe extern "C" fn serialize(this: AnyObject) -> Result, ()>; - unsafe extern "C" fn deserialize(src: &[u8]) -> Result; - unsafe extern "C" fn is_same(this: AnyObject) -> bool; - unsafe extern "C" fn serialize_success(success: ()) -> Result, ()>; - unsafe extern "C" fn serialize_failure(failure: ()) -> Result, ()>; - unsafe extern "C" fn deserialize_success(src: &[u8]) -> Result<(), ()>; - unsafe extern "C" fn deserialize_failure(src: &[u8]) -> Result<(), ()>; -} +impl std::ops::Deref for FFIBox { + type Target = T; -impl IntoOperationVTable for D -where - D: GiteratedOperation, - O: GiteratedObject, -{ - unsafe extern "C" fn serialize(this: AnyObject) -> Result, ()> { - todo!() - } - - unsafe extern "C" fn deserialize(src: &[u8]) -> Result { - let deserialized: D = serde_json::from_slice(src).unwrap(); - - Ok(AnyOperation { - inner: FFIBox::from_box(Box::new(deserialized)).untyped(), - vtable: OperationVTable::new::(), - }) - } - - unsafe extern "C" fn is_same(this: AnyObject) -> bool { - todo!() - } - - unsafe extern "C" fn serialize_success(success: ()) -> Result, ()> { - todo!() - } - - unsafe extern "C" fn serialize_failure(failure: ()) -> Result, ()> { - todo!() - } - - unsafe extern "C" fn deserialize_success(src: &[u8]) -> Result<(), ()> { - todo!() - } - - unsafe extern "C" fn deserialize_failure(src: &[u8]) -> Result<(), ()> { - todo!() + fn deref(&self) -> &Self::Target { + unsafe { self.0.as_ref() }.unwrap() } } - -pub trait IntoSettingVTable { - unsafe extern "C" fn deserialize(src: &[u8]) -> Result<(), ()>; - unsafe extern "C" fn serialize(this: NewAnySetting) -> Result, ()>; -} - -impl IntoSettingVTable for S -where - S: Setting, -{ - unsafe extern "C" fn deserialize(src: &[u8]) -> Result<(), ()> { - todo!() - } - - unsafe extern "C" fn serialize(this: NewAnySetting) -> Result, ()> { - todo!() - } -} - -pub trait IntoValueVTable { - unsafe extern "C" fn deserialize(src: &[u8]) -> Result; - unsafe extern "C" fn serialize(this: NewAnyValue) -> Result, ()>; -} - -impl IntoValueVTable for V -where - O: GiteratedObject, - V: GiteratedObjectValue, -{ - unsafe extern "C" fn deserialize(src: &[u8]) -> Result { - let _guard = trace_span!( - "deserialize value", - object = O::object_name(), - value = V::value_name() - ); - - trace!("Deserializing"); - let deserialized: V = serde_json::from_slice(src).unwrap(); - - Ok(NewAnyValue { - inner: FFIBox::from_box(Box::new(deserialized)).untyped(), - vtable: ValueVTable::new::(), - }) - } - - unsafe extern "C" fn serialize(this: NewAnyValue) -> Result, ()> { - todo!() - } -} - -#[repr(C)] -pub struct AnyObject { - /// A pointer to the plugin-local object type. We are not capable of - /// knowing what this type is, we use the provided vtable. - inner: FFIBox<()>, - vtable: ObjectVtable, -} - -impl AnyObject { - pub fn new(inner: T) -> Self { - Self { - inner: FFIBox::from_box(Box::new(inner)).untyped(), - vtable: ObjectVtable::new::(), - } - } -} - -impl AnyObject { - pub unsafe fn transmute_owned(&mut self) -> Box { - Box::from_raw(self.inner.0 as *mut T) - } - - pub unsafe fn transmute_ref(&self) -> &T { - let ptr: *const T = transmute(self.inner.0); - - ptr.as_ref().unwrap() - } -} - -#[repr(C)] -pub struct FFISettingMeta(); - -#[repr(C)] -pub struct FFIValueMeta(); - -#[repr(C)] -pub struct HostVTable { - register_operation: unsafe extern "C" fn(&str, &str, FFIOperationHandler), - register_value_change: unsafe extern "C" fn(&str, &str, FFIValueChangeHandler), - register_object: unsafe extern "C" fn(&str, ObjectVtable), - register_setting: unsafe extern "C" fn(&str, &str, FFISettingMeta), - register_value: unsafe extern "C" fn(&str, &str, FFIValueMeta), -} - -#[repr(C)] -#[derive(Clone, Copy)] -pub struct InitializationVTable { - pub register_value_change: - unsafe extern "C" fn(*mut PluginInitializationState, &str, &str, FFIValueChangeHandler), - pub register_object: - unsafe extern "C" fn(*mut PluginInitializationState, &'static str, ObjectVtable), - pub register_operation: unsafe extern "C" fn( - *mut PluginInitializationState, - &'static str, - &'static str, - OperationVTable, - ), - pub register_setting: unsafe extern "C" fn( - *mut PluginInitializationState, - &'static str, - &'static str, - SettingVtable, - ), - pub register_value: unsafe extern "C" fn( - *mut PluginInitializationState, - &'static str, - &'static str, - ValueVTable, - ), - - pub operation_handler: unsafe extern "C" fn( - *mut PluginInitializationState, - &'static str, - &'static str, - OperationHandlerCallback, - ), - - pub value_getter: unsafe extern "C" fn( - *mut PluginInitializationState, - &'static str, - &'static str, - ValueGetterCallback, - ), - - pub setting_getter: unsafe extern "C" fn( - *mut PluginInitializationState, - &'static str, - &'static str, - SettingGetterCallback, - ), -} - -impl Debug for InitializationVTable { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("InitializationVTable").finish() - } -} - -unsafe impl Sync for InitializationVTable {} -unsafe impl Send for InitializationVTable {} diff --git a/giterated-plugins/giterated-plugin/src/new_stack/mod.rs b/giterated-plugins/giterated-plugin/src/new_stack/mod.rs index 622bc92..4b59e41 100644 --- a/giterated-plugins/giterated-plugin/src/new_stack/mod.rs +++ b/giterated-plugins/giterated-plugin/src/new_stack/mod.rs @@ -1,9 +1,14 @@ pub mod operation_walker; +pub mod runtime_handler; use std::{ any::type_name, collections::HashMap, fmt::Debug, mem::transmute, ptr::null_mut, sync::Arc, }; +use giterated_models::{ + error::OperationError, instance::Instance, object::GiteratedObject, + operation::GiteratedOperation, +}; use semver::Version; use tracing::{debug, debug_span, field::DebugValue, span, trace, trace_span, warn, Level}; @@ -13,12 +18,25 @@ use crate::{ ValueChangeCallback, ValueGetterCallback, }, handle::{PluginHandle, PluginInitializationState}, - AnyObject, AnyOperation, FFIBox, NewAnySetting, NewAnyValue, ObjectVtable, OperationVTable, - SettingVtable, ValueVTable, + vtable::{ObjectVtable, OperationVTable, SettingVtable, ValueVTable}, }; use self::operation_walker::OperationHandlerRules; +pub struct State(pub S); + +impl std::ops::Deref for State { + type Target = S; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +pub struct OperationState { + pub our_instance: Instance, +} + #[derive(Default)] pub struct TypeMetadata { pub objects: HashMap<&'static str, ObjectVtable>, @@ -224,10 +242,20 @@ impl Runtime { operation_name: &str, object: &str, operation_payload: &[u8], - ) -> Result<(), HandlerError> { - let rules = self.handlers.handle_operation(object_kind, operation_name); + ) -> Result<(), OperationError<()>> { + // let rules = self.handlers.handle_operation(object_kind, operation_name); + + // rules.handle(object, operation_payload) + + todo!() + } - rules.handle(object, operation_payload) + pub fn handle_typed>( + &self, + object: O, + operation: D, + ) -> Result> { + todo!() } } @@ -241,6 +269,9 @@ pub struct RuntimeHandlers { setting_change: HashMap, (RuntimeDomain, SettingChangeCallback)>, } +unsafe impl Send for RuntimeHandlers {} +unsafe impl Sync for RuntimeHandlers {} + impl RuntimeHandlers { pub fn operation_handler( &mut self, diff --git a/giterated-plugins/giterated-plugin/src/new_stack/operation_walker.rs b/giterated-plugins/giterated-plugin/src/new_stack/operation_walker.rs index 28e694a..bb9f6f6 100644 --- a/giterated-plugins/giterated-plugin/src/new_stack/operation_walker.rs +++ b/giterated-plugins/giterated-plugin/src/new_stack/operation_walker.rs @@ -1,3 +1,4 @@ +use crate::callback::RuntimeState; use giterated_models::{operation::GiteratedOperation, settings::GetSetting, value::GetValue}; use tracing::{debug_span, trace, trace_span}; @@ -39,7 +40,12 @@ impl<'o> OperationHandlerRules<'o> { } } - pub fn handle(&self, object: &str, operation_payload: &[u8]) -> Result<(), HandlerError> { + pub fn handle( + &self, + runtime_state: &RuntimeState, + object: &str, + operation_payload: &[u8], + ) -> Result<(), HandlerError> { // object_kind: `any` // operation_kind: `typed` if let Some(handler) = self @@ -210,6 +216,7 @@ impl<'o> OperationHandlerRules<'o> { let result = unsafe { (handler.func)( handler.callback_ptr, + runtime_state, &domain.plugin.state, object, operation, diff --git a/giterated-plugins/giterated-plugin/src/new_stack/runtime_handler.rs b/giterated-plugins/giterated-plugin/src/new_stack/runtime_handler.rs new file mode 100644 index 0000000..343ce53 --- /dev/null +++ b/giterated-plugins/giterated-plugin/src/new_stack/runtime_handler.rs @@ -0,0 +1,34 @@ +use giterated_models::error::OperationError; + +use crate::vtable::{AnyFailure, AnySuccess, OperationVTable}; + +pub struct RuntimeHandle { + inner: RuntimeHandleInner, +} + +impl RuntimeHandle { + pub async fn handle_serialized( + &self, + operation_name: &str, + object: &str, + operation: &[u8], + ) -> Result, OperationError>> { + todo!() + } +} + +#[repr(C)] +struct RuntimeHandleInner { + handle_serialized: unsafe extern "C" fn( + object_kind: &str, + operation_name: &str, + object: &str, + operation_payload: &[u8], + ) -> HandlerResult, +} + +#[repr(C)] +struct HandlerResult { + operation_vtable: OperationVTable, + result: Result>, +} diff --git a/giterated-plugins/giterated-plugin/src/vtable/host.rs b/giterated-plugins/giterated-plugin/src/vtable/host.rs new file mode 100644 index 0000000..f1204b2 --- /dev/null +++ b/giterated-plugins/giterated-plugin/src/vtable/host.rs @@ -0,0 +1,64 @@ +use super::{ObjectVtable, OperationVTable, SettingVtable, ValueVTable}; +use crate::{ + callback::{OperationHandlerCallback, SettingGetterCallback, ValueGetterCallback}, + handle::PluginInitializationState, +}; +use std::fmt::Debug; + +#[repr(C)] +pub struct HostVTable {} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct InitializationVTable { + pub register_object: + unsafe extern "C" fn(*mut PluginInitializationState, &'static str, ObjectVtable), + pub register_operation: unsafe extern "C" fn( + *mut PluginInitializationState, + &'static str, + &'static str, + OperationVTable, + ), + pub register_setting: unsafe extern "C" fn( + *mut PluginInitializationState, + &'static str, + &'static str, + SettingVtable, + ), + pub register_value: unsafe extern "C" fn( + *mut PluginInitializationState, + &'static str, + &'static str, + ValueVTable, + ), + + pub operation_handler: unsafe extern "C" fn( + *mut PluginInitializationState, + &'static str, + &'static str, + OperationHandlerCallback, + ), + + pub value_getter: unsafe extern "C" fn( + *mut PluginInitializationState, + &'static str, + &'static str, + ValueGetterCallback, + ), + + pub setting_getter: unsafe extern "C" fn( + *mut PluginInitializationState, + &'static str, + &'static str, + SettingGetterCallback, + ), +} + +impl Debug for InitializationVTable { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("InitializationVTable").finish() + } +} + +unsafe impl Sync for InitializationVTable {} +unsafe impl Send for InitializationVTable {} diff --git a/giterated-plugins/giterated-plugin/src/vtable/mod.rs b/giterated-plugins/giterated-plugin/src/vtable/mod.rs index e64bf7b..543839a 100644 --- a/giterated-plugins/giterated-plugin/src/vtable/mod.rs +++ b/giterated-plugins/giterated-plugin/src/vtable/mod.rs @@ -1,3 +1,13 @@ //! Giterated's VTable System //! //! Docs here? :) +mod setting; +pub use setting::*; +mod operation; +pub use operation::*; +mod object; +pub use object::*; +mod value; +pub use value::*; +mod host; +pub use host::*; diff --git a/giterated-plugins/giterated-plugin/src/vtable/object.rs b/giterated-plugins/giterated-plugin/src/vtable/object.rs new file mode 100644 index 0000000..dc00436 --- /dev/null +++ b/giterated-plugins/giterated-plugin/src/vtable/object.rs @@ -0,0 +1,109 @@ +use std::mem::transmute; + +use giterated_models::object::GiteratedObject; + +use crate::FFIBox; + +#[derive(Clone, Copy)] +#[repr(C)] +pub struct ObjectVtable { + object_kind: *const u8, + object_kind_len: usize, + pub to_str: unsafe extern "C" fn(AnyObject) -> FFIBox, + pub from_str: unsafe extern "C" fn(&str) -> Result>, + pub home_uri: unsafe extern "C" fn(&AnyObject) -> FFIBox, + pub is_same: unsafe extern "C" fn(AnyObject) -> bool, +} + +impl ObjectVtable { + pub fn new() -> Self { + let object_kind = T::object_kind().as_ptr(); + let object_kind_len = T::object_kind().len(); + + Self { + to_str: T::to_str, + from_str: T::from_str, + home_uri: T::home_uri, + is_same: T::is_same, + object_kind, + object_kind_len, + } + } + + pub fn kind(&self) -> &'static str { + let slice = unsafe { std::slice::from_raw_parts(self.object_kind, self.object_kind_len) }; + + std::str::from_utf8(slice).unwrap() + } +} + +pub trait IntoObjectVTable { + fn object_kind() -> &'static str; + unsafe extern "C" fn to_str(this: AnyObject) -> FFIBox; + unsafe extern "C" fn from_str(src: &str) -> Result>; + unsafe extern "C" fn home_uri(this: &AnyObject) -> FFIBox; + unsafe extern "C" fn is_same(other: AnyObject) -> bool; +} + +impl IntoObjectVTable for T { + unsafe extern "C" fn to_str(mut this: AnyObject) -> FFIBox { + let this: &Box = this.transmute_ref(); + + let result = this.to_string(); + + FFIBox::from_box(result.into_boxed_str()) + } + + unsafe extern "C" fn from_str(src: &str) -> Result> { + let result = T::from_object_str(src).unwrap(); + + let any_object = AnyObject::new(result); + + Ok(any_object) + } + + unsafe extern "C" fn home_uri(this: &AnyObject) -> FFIBox { + todo!() + } + + unsafe extern "C" fn is_same(other: AnyObject) -> bool { + todo!() + } + + fn object_kind() -> &'static str { + todo!() + } +} + +#[repr(C)] +pub struct AnyObject { + /// A pointer to the plugin-local object type. We are not capable of + /// knowing what this type is, we use the provided vtable. + inner: FFIBox<()>, + vtable: ObjectVtable, +} + +impl AnyObject { + pub fn new(inner: T) -> Self { + Self { + inner: FFIBox::from_box(Box::new(inner)).untyped(), + vtable: ObjectVtable::new::(), + } + } + + pub fn vtable(&self) -> ObjectVtable { + self.vtable + } +} + +impl AnyObject { + pub unsafe fn transmute_owned(&mut self) -> Box { + Box::from_raw(self.inner.0 as *mut T) + } + + pub unsafe fn transmute_ref(&self) -> &T { + let ptr: *const T = transmute(self.inner.0); + + ptr.as_ref().unwrap() + } +} diff --git a/giterated-plugins/giterated-plugin/src/vtable/operation.rs b/giterated-plugins/giterated-plugin/src/vtable/operation.rs new file mode 100644 index 0000000..5ecfa36 --- /dev/null +++ b/giterated-plugins/giterated-plugin/src/vtable/operation.rs @@ -0,0 +1,136 @@ +use std::mem::transmute; + +use giterated_models::{object::GiteratedObject, operation::GiteratedOperation}; + +use crate::FFIBox; + +use super::AnyObject; + +#[derive(Clone, Copy)] +#[repr(C)] +pub struct OperationVTable { + operation_kind: *const u8, + operation_kind_len: usize, + pub serialize: unsafe extern "C" fn(&AnyOperation) -> Result, ()>, + pub deserialize: unsafe extern "C" fn(&[u8]) -> Result, + pub is_same: unsafe extern "C" fn(AnyObject) -> bool, + pub serialize_success: unsafe extern "C" fn(()) -> Result, ()>, + pub serialize_failure: unsafe extern "C" fn(()) -> Result, ()>, + pub deserialize_success: unsafe extern "C" fn(&[u8]) -> Result, + pub deserialize_failure: unsafe extern "C" fn(&[u8]) -> Result, +} + +impl OperationVTable { + pub fn new>() -> Self { + let operation_kind = T::operation_kind().as_ptr(); + let operation_kind_len = T::operation_kind().len(); + + Self { + serialize: T::serialize, + deserialize: T::deserialize, + is_same: T::is_same, + serialize_success: T::serialize_success, + serialize_failure: T::serialize_failure, + deserialize_success: T::deserialize_success, + deserialize_failure: T::deserialize_failure, + operation_kind, + operation_kind_len, + } + } + + pub fn kind(&self) -> &'static str { + let slice = + unsafe { std::slice::from_raw_parts(self.operation_kind, self.operation_kind_len) }; + + std::str::from_utf8(slice).unwrap() + } +} + +pub struct AnyOperation { + /// A pointer to the plugin-local object type. We are not capable of + /// knowing what this type is, we use the provided vtable. + inner: FFIBox<()>, + vtable: OperationVTable, +} + +impl AnyOperation { + pub unsafe fn transmute_owned(&mut self) -> Box { + Box::from_raw(self.inner.0 as *mut T) + } + + pub unsafe fn transmute_ref(&self) -> &T { + let ptr: *const T = transmute(self.inner.0); + + ptr.as_ref().unwrap() + } + + pub fn vtable(&self) -> OperationVTable { + self.vtable + } +} + +#[repr(C)] +pub struct AnySuccess { + inner: FFIBox<()>, + vtable: OperationVTable, +} + +#[repr(C)] +pub struct AnyFailure { + inner: FFIBox<()>, + vtable: OperationVTable, +} + +pub trait IntoOperationVTable { + fn operation_kind() -> &'static str; + unsafe extern "C" fn serialize(this: &AnyOperation) -> Result, ()>; + unsafe extern "C" fn deserialize(src: &[u8]) -> Result; + unsafe extern "C" fn is_same(this: AnyObject) -> bool; + unsafe extern "C" fn serialize_success(success: ()) -> Result, ()>; + unsafe extern "C" fn serialize_failure(failure: ()) -> Result, ()>; + unsafe extern "C" fn deserialize_success(src: &[u8]) -> Result; + unsafe extern "C" fn deserialize_failure(src: &[u8]) -> Result; +} + +impl IntoOperationVTable for D +where + D: GiteratedOperation, + O: GiteratedObject, +{ + unsafe extern "C" fn serialize(this: &AnyOperation) -> Result, ()> { + todo!() + } + + unsafe extern "C" fn deserialize(src: &[u8]) -> Result { + let deserialized: D = serde_json::from_slice(src).unwrap(); + + Ok(AnyOperation { + inner: FFIBox::from_box(Box::new(deserialized)).untyped(), + vtable: OperationVTable::new::(), + }) + } + + unsafe extern "C" fn is_same(this: AnyObject) -> bool { + todo!() + } + + unsafe extern "C" fn serialize_success(success: ()) -> Result, ()> { + todo!() + } + + unsafe extern "C" fn serialize_failure(failure: ()) -> Result, ()> { + todo!() + } + + unsafe extern "C" fn deserialize_success(src: &[u8]) -> Result { + todo!() + } + + unsafe extern "C" fn deserialize_failure(src: &[u8]) -> Result { + todo!() + } + + fn operation_kind() -> &'static str { + todo!() + } +} diff --git a/giterated-plugins/giterated-plugin/src/vtable/setting.rs b/giterated-plugins/giterated-plugin/src/vtable/setting.rs new file mode 100644 index 0000000..4fd768f --- /dev/null +++ b/giterated-plugins/giterated-plugin/src/vtable/setting.rs @@ -0,0 +1,66 @@ +use std::mem::transmute; + +use giterated_models::settings::Setting; + +use crate::FFIBox; + +#[repr(C)] +pub struct NewAnySetting { + /// A pointer to the plugin-local object type. We are not capable of + /// knowing what this type is, we use the provided vtable. + inner: FFIBox<()>, + vtable: SettingVtable, +} + +impl NewAnySetting { + pub fn new(value: V) -> Self { + Self { + inner: FFIBox::from_box(Box::new(value)).untyped(), + vtable: SettingVtable::new::(), + } + } + + pub unsafe fn transmute_owned(self) -> Box { + Box::from_raw(self.inner.0 as *mut T) + } + + pub unsafe fn transmute_ref(&self) -> &T { + let ptr: *const T = transmute(self.inner.0); + + ptr.as_ref().unwrap() + } +} + +#[derive(Clone, Copy)] +#[repr(C)] +pub struct SettingVtable { + pub deserialize: unsafe extern "C" fn(&[u8]) -> Result<(), ()>, + pub serialize: unsafe extern "C" fn(NewAnySetting) -> Result, ()>, +} + +impl SettingVtable { + pub fn new() -> Self { + Self { + deserialize: T::deserialize, + serialize: T::serialize, + } + } +} + +pub trait IntoSettingVTable { + unsafe extern "C" fn deserialize(src: &[u8]) -> Result<(), ()>; + unsafe extern "C" fn serialize(this: NewAnySetting) -> Result, ()>; +} + +impl IntoSettingVTable for S +where + S: Setting, +{ + unsafe extern "C" fn deserialize(src: &[u8]) -> Result<(), ()> { + todo!() + } + + unsafe extern "C" fn serialize(this: NewAnySetting) -> Result, ()> { + todo!() + } +} diff --git a/giterated-plugins/giterated-plugin/src/vtable/value.rs b/giterated-plugins/giterated-plugin/src/vtable/value.rs new file mode 100644 index 0000000..ba9eb93 --- /dev/null +++ b/giterated-plugins/giterated-plugin/src/vtable/value.rs @@ -0,0 +1,67 @@ +use giterated_models::{object::GiteratedObject, value::GiteratedObjectValue}; + +use crate::FFIBox; + +#[repr(C)] +pub struct NewAnyValue { + /// A pointer to the plugin-local object type. We are not capable of + /// knowing what this type is, we use the provided vtable. + inner: FFIBox<()>, + vtable: ValueVTable, +} + +impl NewAnyValue { + pub fn new>(value: V) -> Self { + NewAnyValue { + inner: FFIBox::from_box(Box::new(value)).untyped(), + vtable: ValueVTable::new::(), + } + } +} + +#[derive(Clone, Copy)] +#[repr(C)] +pub struct ValueVTable { + pub deserialize: unsafe extern "C" fn(&[u8]) -> Result, + pub serialize: unsafe extern "C" fn(NewAnyValue) -> Result, ()>, +} + +impl ValueVTable { + pub fn new>() -> Self { + Self { + deserialize: T::deserialize, + serialize: T::serialize, + } + } +} + +pub trait IntoValueVTable { + unsafe extern "C" fn deserialize(src: &[u8]) -> Result; + unsafe extern "C" fn serialize(this: NewAnyValue) -> Result, ()>; +} + +impl IntoValueVTable for V +where + O: GiteratedObject, + V: GiteratedObjectValue, +{ + unsafe extern "C" fn deserialize(src: &[u8]) -> Result { + let _guard = trace_span!( + "deserialize value", + object = O::object_name(), + value = V::value_name() + ); + + trace!("Deserializing"); + let deserialized: V = serde_json::from_slice(src).unwrap(); + + Ok(NewAnyValue { + inner: FFIBox::from_box(Box::new(deserialized)).untyped(), + vtable: ValueVTable::new::(), + }) + } + + unsafe extern "C" fn serialize(this: NewAnyValue) -> Result, ()> { + todo!() + } +} diff --git a/giterated-plugins/giterated-protocol/Cargo.toml b/giterated-plugins/giterated-protocol/Cargo.toml new file mode 100644 index 0000000..13ddc40 --- /dev/null +++ b/giterated-plugins/giterated-protocol/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "giterated-protocol" +version = "0.1.0" +edition = "2021" + +[lib] +name = "giterated_protocol_plugin" +path = "src/lib.rs" +crate-type = ["dylib", "rlib"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +giterated-plugin = { path = "../giterated-plugin" } +giterated-models = { path = "../../giterated-models" } +serde = { version = "1.0", features = [ "derive" ]} +anyhow = "1" +giterated-plugin-sys = { path = "../giterated-plugin-sys" } +toml = { version = "0.7" } +tracing = "0.1" +tracing-subscriber = "0.3" +serde_json = "1.0" +rand = "0.8" +rsa = {version = "0.9", features = ["sha2"]} +tokio-tungstenite = { version = "0.20" } +tokio = { version = "1.32.0", features = ["full"] } +thiserror = "1" +bincode = "1.3" +futures-util = "0.3" +async-trait = "0.1" \ No newline at end of file diff --git a/giterated-plugins/giterated-protocol/src/handlers.rs b/giterated-plugins/giterated-protocol/src/handlers.rs new file mode 100644 index 0000000..02178ee --- /dev/null +++ b/giterated-plugins/giterated-protocol/src/handlers.rs @@ -0,0 +1,255 @@ +use std::{fmt::Display, net::SocketAddr, str::FromStr, sync::Arc}; + +use anyhow::Error; +use futures_util::{SinkExt, StreamExt}; +use giterated_models::{ + error::{NetworkOperationError, OperationError}, + instance::Instance, + object::GiteratedObject, + operation::GiteratedOperation, +}; +use giterated_plugin::{ + new_stack::{runtime_handler::RuntimeHandle, Runtime}, + AnyFailure, AnyObject, AnyOperation, AnySuccess, +}; +use serde::{Deserialize, Serialize}; +use tokio::net::TcpStream; +use tokio_tungstenite::{connect_async, tungstenite::Message, MaybeTlsStream, WebSocketStream}; + +use crate::{Authenticated, GiteratedMessage, ProtocolState, RemoteError}; + +pub async fn handle_network_operation( + state: ProtocolState, + object: NetworkedObject, + operation: NetworkedOperation, + runtime: RuntimeHandle, +) -> Result, OperationError>> { + trace!("Handle network operation {}", operation.name); + + runtime + .handle_serialized(&object.0, &operation.name, &operation.payload) + .await +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct NetworkedObject(pub String); + +impl FromStr for NetworkedObject { + type Err = (); + + fn from_str(s: &str) -> Result { + Ok(NetworkedObject(s.to_string())) + } +} + +impl Display for NetworkedObject { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(&self.0) + } +} + +impl GiteratedObject for NetworkedObject { + fn object_name() -> &'static str { + "networked_object" + } + + fn from_object_str(_object_str: &str) -> Result { + todo!() + } + + fn home_uri(&self) -> String { + todo!() + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct NetworkedOperation { + pub name: String, + pub payload: Vec, +} + +impl NetworkedOperation { + pub fn new(name: String, payload: Vec) -> Self { + Self { name, payload } + } +} + +impl GiteratedOperation for NetworkedOperation { + type Success = Vec; + + type Failure = Vec; + + fn operation_name() -> &'static str { + "networked_operation" + } +} + +/// Handler which will attempt to resolve any operation that doesn't resolve locally +/// against a remote instance. +pub async fn try_handle_with_remote( + state: ProtocolState, + object: AnyObject, + operation: AnyOperation, +) -> Result> { + // if object.is::() { + // return Err(OperationError::Unhandled); + // } + // trace!( + // "Try handling object operation {}::{} with remote", + // object.kind(), + // operation.kind().operation_name + // ); + // TODO: + // Ideally we support pass-through on object types that aren't used locally. + // For now, we aren't worrying about that. + let object_meta = object.vtable().clone(); + + let operation_meta = operation.vtable().clone(); + + // trace!( + // "Serializing with {}::{}", + // operation.kind().object_name, + // operation.kind().operation_name + // ); + + let object_home_uri = unsafe { (object_meta.home_uri)(&object) }; + + if let Some(home_uri) = state.home_uri { + if &home_uri == object_home_uri.as_ref() { + // This isn't a remote request, requests aren't supposed to hit this layer + // if they're not remote. + // warn!("Try handling object operation {}::{}, resolved object home uri as local home uri. This is a bug.", object.kind(), + // operation.kind().operation_name); + + return Err(OperationError::Unhandled); + } + } + + // trace!( + // "Handling object operation {}::{} sending payload", + // object.kind(), + // operation.kind().operation_name + // ); + + let object = NetworkedObject(unsafe { (object_meta.to_str)(object).as_ref().to_string() }); + + let payload = unsafe { (operation_meta.serialize)(&operation) }.unwrap(); + let payload = Vec::from(payload.as_ref()); + + let operation = NetworkedOperation::new(operation_meta.kind().to_string(), payload); + + // let authenticated = Authenticated::new(object, operation); + + let message = GiteratedMessage { + object, + operation: NetworkedOperation::operation_name().to_string(), + payload: operation, + }; + + let authenticated = Authenticated::new(message); + + let mut socket: WebSocketStream> = connect_to( + &Instance::from_str(&object_home_uri).unwrap(), + &Some(("127.0.0.1:1111").parse().unwrap()), + ) + .await + .unwrap(); + + // TODO AUTH + + let result: Result, OperationError>> = + send_expect(&mut socket, authenticated).await; + + match result { + Ok(success) => { + let success = unsafe { (operation_meta.deserialize_success)(&success) }.unwrap(); + + Ok(success) + } + Err(err) => Err(match err { + OperationError::Operation(failure) => { + let failure = unsafe { (operation_meta.deserialize_failure)(&failure) }.unwrap(); + + OperationError::Operation(failure) + } + OperationError::Internal(internal) => OperationError::Internal(internal), + OperationError::Unhandled => OperationError::Unhandled, + }), + } +} + +type Socket = WebSocketStream>; + +async fn connect_to( + instance: &Instance, + + socket_addr: &Option, +) -> Result { + if let Some(addr) = socket_addr { + info!( + "Connecting to {}", + format!("ws://{}/.giterated/daemon/", addr) + ); + + let (websocket, _response) = + connect_async(&format!("ws://{}/.giterated/daemon/", addr)).await?; + + info!("Connection established with {}", addr); + + Ok(websocket) + } else { + info!( + "Connecting to {}", + format!("wss://{}/.giterated/daemon/", instance.0) + ); + + let (websocket, _response) = + connect_async(&format!("wss://{}/.giterated/daemon/", instance.0)).await?; + + info!("Connection established with {}", instance.0); + + Ok(websocket) + } +} + +async fn send_expect>( + socket: &mut Socket, + message: Authenticated, +) -> Result, OperationError>> { + let payload = bincode::serialize(&message.into_payload()).unwrap(); + + socket.send(Message::Binary(payload)).await.unwrap(); + + while let Some(message) = socket.next().await { + let payload = match message.unwrap() { + Message::Binary(payload) => payload, + + _ => { + continue; + } + }; + + let raw_result = + bincode::deserialize::, NetworkOperationError>>>(&payload) + .map_err(|e| OperationError::Internal(Error::from(e)))?; + + trace!( + "Received response for networked operation {}::{}.", + O::object_name(), + D::operation_name() + ); + + return match raw_result { + Ok(success) => Ok(success), + Err(err) => Err(match err { + NetworkOperationError::Operation(operation_error) => { + OperationError::Operation(operation_error) + } + NetworkOperationError::Internal => OperationError::Internal(RemoteError.into()), + NetworkOperationError::Unhandled => OperationError::Unhandled, + }), + }; + } + + panic!() +} diff --git a/giterated-plugins/giterated-protocol/src/lib.rs b/giterated-plugins/giterated-protocol/src/lib.rs new file mode 100644 index 0000000..56f5600 --- /dev/null +++ b/giterated-plugins/giterated-protocol/src/lib.rs @@ -0,0 +1,259 @@ +use std::{str::FromStr, sync::Arc}; + +use giterated_models::{ + authenticated::{InstanceSignature, UserAuthenticationToken}, + instance::Instance, + object::GiteratedObject, + operation::GiteratedOperation, + user::User, +}; +use handlers::{NetworkedObject, NetworkedOperation}; +use object::NetworkAnyObject; +use operations::NetworkAnyOperation; +use rsa::{ + pkcs1::DecodeRsaPrivateKey, + pss::SigningKey, + sha2::Sha256, + signature::{RandomizedSigner, SignatureEncoding}, + RsaPrivateKey, +}; +use serde::{Deserialize, Serialize}; +use std::fmt::Debug; + +pub mod handlers; +pub mod object; +pub mod operations; + +#[macro_use] +extern crate tracing; + +#[derive(Clone)] +pub struct NetworkOperationState { + authentication: Vec>, +} + +impl NetworkOperationState { + pub fn new() -> Self { + Self { + authentication: vec![], + } + } + + pub fn authenticate( + &mut self, + provider: impl AuthenticationSourceProviders + Send + Sync + 'static, + ) { + self.authentication.push(Arc::new(provider)) + } +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)] +pub struct AuthenticatedPayload { + pub source: Vec, + pub object: String, + pub operation: String, + pub payload: Vec, +} + +impl AuthenticatedPayload { + pub fn into_message(self) -> GiteratedMessage { + GiteratedMessage { + object: NetworkedObject::from_str(&self.object).unwrap(), + operation: self.operation, + payload: serde_json::from_slice(&self.payload).unwrap(), + } + } +} + +pub trait AuthenticationSourceProvider: Debug { + fn authenticate(&self, payload: &Vec) -> AuthenticationSource; +} + +pub trait AuthenticationSourceProviders: Debug { + fn authenticate_all(&self, payload: &Vec) -> Vec; +} + +impl AuthenticationSourceProviders for A +where + A: AuthenticationSourceProvider, +{ + fn authenticate_all(&self, payload: &Vec) -> Vec { + vec![self.authenticate(payload)] + } +} + +impl AuthenticationSourceProviders for (A, B) +where + A: AuthenticationSourceProvider, + B: AuthenticationSourceProvider, +{ + fn authenticate_all(&self, payload: &Vec) -> Vec { + let (first, second) = self; + + vec![first.authenticate(payload), second.authenticate(payload)] + } +} + +#[derive(Clone, Debug)] +pub struct UserAuthenticator { + pub user: User, + pub token: UserAuthenticationToken, +} + +impl AuthenticationSourceProvider for UserAuthenticator { + fn authenticate(&self, _payload: &Vec) -> AuthenticationSource { + AuthenticationSource::User { + user: self.user.clone(), + token: self.token.clone(), + } + } +} + +#[derive(Debug, Clone)] +pub struct InstanceAuthenticator { + pub instance: Instance, + pub private_key: String, +} + +impl AuthenticationSourceProvider for InstanceAuthenticator { + fn authenticate(&self, payload: &Vec) -> AuthenticationSource { + let mut rng = rand::thread_rng(); + + let private_key = RsaPrivateKey::from_pkcs1_pem(&self.private_key).unwrap(); + let signing_key = SigningKey::::new(private_key); + let signature = signing_key.sign_with_rng(&mut rng, payload); + + AuthenticationSource::Instance { + instance: self.instance.clone(), + // TODO: Actually parse signature from private key + signature: InstanceSignature(signature.to_bytes().into_vec()), + } + } +} + +#[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] +pub enum AuthenticationSource { + User { + user: User, + token: UserAuthenticationToken, + }, + Instance { + instance: Instance, + signature: InstanceSignature, + }, +} + +#[derive(Serialize)] +#[serde(bound(deserialize = "O: GiteratedObject, V: GiteratedOperation"))] +pub struct GiteratedMessage> { + #[serde(with = "string")] + pub object: O, + pub operation: String, + pub payload: V, +} + +#[allow(unused)] +mod string { + use std::fmt::Display; + use std::str::FromStr; + + use serde::{de, Deserialize, Deserializer, Serializer}; + + pub fn serialize(value: &T, serializer: S) -> Result + where + T: Display, + S: Serializer, + { + serializer.collect_str(value) + } + + pub fn deserialize<'de, T, D>(deserializer: D) -> Result + where + T: FromStr, + T::Err: Display, + D: Deserializer<'de>, + { + String::deserialize(deserializer)? + .parse() + .map_err(de::Error::custom) + } +} + +impl GiteratedMessage { + pub fn try_into>( + &self, + ) -> Result, ()> { + let object = O::from_object_str(&self.object.0).map_err(|_| ())?; + let payload = serde_json::from_slice::(&self.payload.0).map_err(|_| ())?; + + Ok(GiteratedMessage { + object, + operation: self.operation.clone(), + payload, + }) + } +} + +impl + Debug, O: GiteratedObject + Debug> Debug + for GiteratedMessage +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("GiteratedMessage") + .field("object", &self.object) + .field("operation", &self.operation) + .field("payload", &self.payload) + .finish() + } +} + +#[derive(Debug, Clone, thiserror::Error)] +#[error("a remote internal error occurred")] +pub struct RemoteError; + +#[derive(Debug, thiserror::Error)] +#[error("a remote internal error occurred")] + +pub struct NetworkError; + +#[derive(Debug)] +pub struct Authenticated> { + pub source: Vec>, + pub message: GiteratedMessage, +} + +impl> Authenticated { + pub fn new(message: GiteratedMessage) -> Self { + Self { + source: vec![], + message, + } + } + + pub fn append_authentication( + &mut self, + authentication: Arc, + ) { + self.source.push(authentication); + } + + pub fn into_payload(mut self) -> AuthenticatedPayload { + let payload = serde_json::to_vec(&self.message.payload).unwrap(); + + AuthenticatedPayload { + object: self.message.object.to_string(), + operation: self.message.operation, + source: self + .source + .drain(..) + .map(|provider| provider.as_ref().authenticate_all(&payload)) + .flatten() + .collect::>(), + payload, + } + } +} + +#[derive(Clone, Debug)] +pub struct ProtocolState { + pub home_uri: Option, +} diff --git a/giterated-plugins/giterated-protocol/src/object.rs b/giterated-plugins/giterated-protocol/src/object.rs new file mode 100644 index 0000000..558f1d6 --- /dev/null +++ b/giterated-plugins/giterated-protocol/src/object.rs @@ -0,0 +1,38 @@ +use std::{convert::Infallible, fmt::Display, str::FromStr}; + +use anyhow::Error; +use giterated_models::object::GiteratedObject; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(transparent)] +#[repr(transparent)] +pub struct NetworkAnyObject(pub String); + +impl GiteratedObject for NetworkAnyObject { + fn object_name() -> &'static str { + "network_object" + } + + fn from_object_str(object_str: &str) -> Result { + Ok(Self(object_str.to_string())) + } + + fn home_uri(&self) -> String { + todo!() + } +} + +impl Display for NetworkAnyObject { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(&self.0) + } +} + +impl FromStr for NetworkAnyObject { + type Err = Infallible; + + fn from_str(s: &str) -> Result { + Ok(Self(s.to_owned())) + } +} diff --git a/giterated-plugins/giterated-protocol/src/operations.rs b/giterated-plugins/giterated-protocol/src/operations.rs new file mode 100644 index 0000000..6e54db4 --- /dev/null +++ b/giterated-plugins/giterated-protocol/src/operations.rs @@ -0,0 +1,13 @@ +use giterated_models::{object::GiteratedObject, operation::GiteratedOperation}; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(transparent)] +#[repr(transparent)] +pub struct NetworkAnyOperation(pub Vec); + +impl GiteratedOperation for NetworkAnyOperation { + type Success = Vec; + + type Failure = Vec; +} diff --git a/giterated-protocol/Cargo.toml b/giterated-protocol/Cargo.toml index 9512b23..dc68736 100644 --- a/giterated-protocol/Cargo.toml +++ b/giterated-protocol/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "giterated-protocol" +name = "giterated-protocol-old" version = "0.1.0" authors = ["Amber Kowalski"] edition = "2021" diff --git a/giterated-stack/src/lib.rs b/giterated-stack/src/lib.rs index 9213869..1138f31 100644 --- a/giterated-stack/src/lib.rs +++ b/giterated-stack/src/lib.rs @@ -421,7 +421,6 @@ impl + Send + Sync> FromOperationState, pub instance: Option, pub user: Option, }