Merge branch 'main' into jf/invite

This commit is contained in:
dr-frmr 2023-10-25 11:56:52 -04:00 committed by GitHub
commit 8bbb204690
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 2125 additions and 41 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ modules/**/wit
target.wasm
world
.env
modules/sqlite/sqlite_worker/.cargo/config.toml

View File

@ -8,6 +8,7 @@ Last updated: 10/16/23
git clone git@github.com:uqbar-dao/uqbar.git
git clone git@github.com:uqbar-dao/redb.git
git clone git@github.com:uqbar-dao/rusqlite.git
Make sure the two repos are next to each other in your directory structure.

View File

@ -64,17 +64,24 @@ fn build_app(target_path: &str, name: &str, parent_pkg_path: Option<&str>) {
.unwrap();
}
// Build the module targeting wasm32-wasi
run_command(Command::new("cargo").args(&[
"+nightly",
"build",
"--release",
"--no-default-features",
&format!("--manifest-path={}/Cargo.toml", target_path),
"--target",
"wasm32-wasi",
]))
.unwrap();
let bash_build_path = &format!("{}/build.sh", target_path);
if std::path::Path::new(&bash_build_path).exists() {
let cwd = std::env::current_dir().unwrap();
std::env::set_current_dir(target_path).unwrap();
run_command(&mut Command::new("/bin/bash").arg("build.sh")).unwrap();
std::env::set_current_dir(cwd).unwrap();
} else {
run_command(Command::new("cargo").args(&[
"+nightly",
"build",
"--release",
"--no-default-features",
&format!("--manifest-path={}/Cargo.toml", target_path),
"--target",
"wasm32-wasi",
]))
.unwrap();
}
// Adapt module to component with adapter based on wasi_snapshot_preview1.wasm
run_command(Command::new("wasm-tools").args(&[
"component",
@ -131,7 +138,7 @@ fn main() {
let pwd = std::env::current_dir().unwrap();
// create target.wasm (compiled .wit) & world
// Create target.wasm (compiled .wit) & world
run_command(Command::new("wasm-tools").args(&[
"component",
"wit",

View File

@ -14,7 +14,7 @@ lto = true
anyhow = "1.0"
bincode = "1.3.3"
cargo-component-bindings = { git = "https://github.com/bytecodealliance/cargo-component" }
serde = {version = "1.0", features = ["derive"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0"
wit-bindgen = { version = "0.11.0", default_features = false }

View File

@ -79,14 +79,14 @@ fn handle_message (
}
match message {
Message::Response(r) => {
Message::Response(_) => {
return Err(kv::KeyValueError::UnexpectedResponse.into());
},
Message::Request(Request { ipc, .. }) => {
match process_lib::parse_message_ipc(ipc.clone())? {
kv::KeyValueMessage::New { ref db } => {
// TODO: make atomic
// (1): create vfs
// (1): create vfs drive
// (2): spin up worker, granting vfs caps
// (3): issue new caps
// (4): persist
@ -147,7 +147,7 @@ fn handle_message (
&Request {
inherit: false,
expects_response: None,
ipc,
ipc: ipc.clone(),
metadata: None,
},
None,
@ -156,7 +156,16 @@ fn handle_message (
// (4)
db_to_process.insert(db.into(), spawned_process_id);
// TODO
// TODO: persistence?
send_response(
&Response {
inherit: false,
ipc,
metadata: None,
},
None,
);
},
kv::KeyValueMessage::Write { ref db, .. } => {
forward_if_have_cap(our, "write", db, ipc, db_to_process)?;
@ -178,7 +187,7 @@ impl Guest for Component {
fn init(our: Address) {
print_to_terminal(0, "key_value: begin");
let mut db_to_process: HashMap<String, ProcessId> = HashMap::new();
let mut db_to_process: DbToProcess = HashMap::new();
loop {
match handle_message(&our, &mut db_to_process) {

View File

@ -30,6 +30,3 @@ package = "component:uq-process"
path = "wit"
[package.metadata.component.dependencies]
[package.metadata.component.target.dependencies]
"redb:redb" = { path = "../../../../redb/wit" }

View File

@ -0,0 +1,12 @@
[
{
"process_name": "sqlite",
"process_wasm_path": "/sqlite.wasm",
"on_panic": "Restart",
"request_networking": false,
"request_messaging": [
"vfs:sys:uqbar"
],
"public": true
}
]

View File

@ -0,0 +1,4 @@
{
"package": "sqlite",
"publisher": "uqbar"
}

524
modules/sqlite/sqlite/Cargo.lock generated Normal file
View File

@ -0,0 +1,524 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anyhow"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cargo-component-bindings"
version = "0.1.0"
source = "git+https://github.com/bytecodealliance/cargo-component#6a2996f280dd8671a2a2d3c83cbe09a39225b526"
dependencies = [
"cargo-component-macro",
"wit-bindgen",
]
[[package]]
name = "cargo-component-macro"
version = "0.1.0"
source = "git+https://github.com/bytecodealliance/cargo-component#6a2996f280dd8671a2a2d3c83cbe09a39225b526"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
"wit-bindgen-core",
"wit-bindgen-rust",
"wit-bindgen-rust-lib",
"wit-component",
]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "form_urlencoded"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
dependencies = [
"percent-encoding",
]
[[package]]
name = "hashbrown"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "id-arena"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
[[package]]
name = "idna"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
dependencies = [
"equivalent",
"hashbrown",
"serde",
]
[[package]]
name = "itoa"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "leb128"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]]
name = "log"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "memchr"
version = "2.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
[[package]]
name = "num-traits"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]
[[package]]
name = "paste"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "percent-encoding"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
[[package]]
name = "proc-macro2"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "pulldown-cmark"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998"
dependencies = [
"bitflags 1.3.2",
"memchr",
"unicase",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rmp"
version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20"
dependencies = [
"byteorder",
"num-traits",
"paste",
]
[[package]]
name = "rmp-serde"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a"
dependencies = [
"byteorder",
"rmp",
"serde",
]
[[package]]
name = "ryu"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "semver"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
[[package]]
name = "serde"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "smallvec"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
[[package]]
name = "spdx"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b19b32ed6d899ab23174302ff105c1577e45a06b08d4fe0a9dd13ce804bbbf71"
dependencies = [
"smallvec",
]
[[package]]
name = "sqlite"
version = "0.1.0"
dependencies = [
"anyhow",
"bincode",
"cargo-component-bindings",
"rmp-serde",
"serde",
"serde_json",
"thiserror",
"wit-bindgen",
]
[[package]]
name = "syn"
version = "2.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "unicase"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [
"version_check",
]
[[package]]
name = "unicode-bidi"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]]
name = "unicode-ident"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "url"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasm-encoder"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ba64e81215916eaeb48fee292f29401d69235d62d8b8fd92a7b2844ec5ae5f7"
dependencies = [
"leb128",
]
[[package]]
name = "wasm-metadata"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08dc59d1fa569150851542143ca79438ca56845ccb31696c70225c638e063471"
dependencies = [
"anyhow",
"indexmap",
"serde",
"serde_json",
"spdx",
"wasm-encoder",
"wasmparser",
]
[[package]]
name = "wasmparser"
version = "0.112.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e986b010f47fcce49cf8ea5d5f9e5d2737832f12b53ae8ae785bbe895d0877bf"
dependencies = [
"indexmap",
"semver",
]
[[package]]
name = "wit-bindgen"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8a3e8e965dc50e6eb4410d9a11720719fadc6a1713803ea5f3be390b81c8279"
dependencies = [
"bitflags 2.4.0",
"wit-bindgen-rust-macro",
]
[[package]]
name = "wit-bindgen-core"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77255512565dfbd0b61de466e854918041d1da53c7bc049d6188c6e02643dc1e"
dependencies = [
"anyhow",
"wit-component",
"wit-parser",
]
[[package]]
name = "wit-bindgen-rust"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "399c60e6ea8598d1380e792f13d557007834f0fb799fea6503408cbc5debb4ae"
dependencies = [
"anyhow",
"heck",
"wasm-metadata",
"wit-bindgen-core",
"wit-bindgen-rust-lib",
"wit-component",
]
[[package]]
name = "wit-bindgen-rust-lib"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd9fb7a43c7dc28b0b727d6ae01bf369981229b7539e768fba2b7a4df13feeeb"
dependencies = [
"heck",
"wit-bindgen-core",
]
[[package]]
name = "wit-bindgen-rust-macro"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44cea5ed784da06da0e55836a6c160e7502dbe28771c2368a595e8606243bf22"
dependencies = [
"anyhow",
"proc-macro2",
"syn",
"wit-bindgen-core",
"wit-bindgen-rust",
"wit-bindgen-rust-lib",
"wit-component",
]
[[package]]
name = "wit-component"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66d9f2d16dd55d1a372dcfd4b7a466ea876682a5a3cb97e71ec9eef04affa876"
dependencies = [
"anyhow",
"bitflags 2.4.0",
"indexmap",
"log",
"serde",
"serde_json",
"wasm-encoder",
"wasm-metadata",
"wasmparser",
"wit-parser",
]
[[package]]
name = "wit-parser"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61e8b849bea13cc2315426b16efe6eb6813466d78f5fde69b0bb150c9c40e0dc"
dependencies = [
"anyhow",
"id-arena",
"indexmap",
"log",
"pulldown-cmark",
"semver",
"unicode-xid",
"url",
]

View File

@ -0,0 +1,32 @@
[package]
name = "sqlite"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[profile.release]
panic = "abort"
opt-level = "s"
lto = true
[dependencies]
anyhow = "1.0"
bincode = "1.3.3"
cargo-component-bindings = { git = "https://github.com/bytecodealliance/cargo-component" }
rmp-serde = "1.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0"
wit-bindgen = { version = "0.11.0", default_features = false }
[lib]
crate-type = ["cdylib"]
[package.metadata.component]
package = "component:uq-process"
[package.metadata.component.target]
path = "wit"
[package.metadata.component.dependencies]

View File

@ -0,0 +1 @@
../../../../src/kernel_types.rs

View File

@ -0,0 +1,262 @@
cargo_component_bindings::generate!();
use std::collections::{HashMap, HashSet};
use bindings::component::uq_process::types::*;
use bindings::{create_capability, get_capability, Guest, has_capability, print_to_terminal, receive, send_request, send_response, spawn};
mod kernel_types;
use kernel_types as kt;
mod sqlite_types;
use sqlite_types as sq;
mod process_lib;
struct Component;
const PREFIX: &str = "sqlite-";
type DbToProcess = HashMap<String, ProcessId>;
fn make_vfs_cap(kind: &str, drive: &str) -> String {
serde_json::to_string(&serde_json::json!({
"kind": kind,
"drive": drive,
})).unwrap()
}
fn make_db_cap(kind: &str, db: &str) -> String {
serde_json::to_string(&serde_json::json!({
"kind": kind,
"db": db,
})).unwrap()
}
fn forward_if_have_cap(
our: &Address,
operation_type: &str,
// operation_type: OperationType,
db: &str,
ipc: Option<String>,
db_to_process: &mut DbToProcess,
) -> anyhow::Result<()> {
if has_capability(&make_db_cap(operation_type, db)) {
// forward
let Some(process_id) = db_to_process.get(db) else {
return Err(sq::SqliteError::DbDoesNotExist.into());
};
send_request(
&Address {
node: our.node.clone(),
process: process_id.clone(),
},
&Request {
inherit: true,
expects_response: None,
ipc,
metadata: None,
},
None,
None,
);
return Ok(());
} else {
// reject
return Err(sq::SqliteError::NoCap.into());
}
}
fn handle_message (
our: &Address,
db_to_process: &mut DbToProcess,
read_keywords: &HashSet<String>,
write_keywords: &HashSet<String>,
) -> anyhow::Result<()> {
let (source, message) = receive().unwrap();
// let (source, message) = receive()?;
if our.node != source.node {
return Err(sq::SqliteError::RejectForeign.into());
}
match message {
Message::Response(_) => {
return Err(sq::SqliteError::UnexpectedResponse.into());
},
Message::Request(Request { ipc, .. }) => {
match process_lib::parse_message_ipc(ipc.clone())? {
sq::SqliteMessage::New { ref db } => {
// TODO: make atomic
// (1): create vfs drive
// (2): spin up worker, granting vfs caps
// (3): issue new caps
// (4): persist
if db_to_process.contains_key(db) {
return Err(sq::SqliteError::DbAlreadyExists.into());
}
// (1)
let vfs_address = Address {
node: our.node.clone(),
process: kt::ProcessId::new("vfs", "sys", "uqbar").en_wit(),
};
let vfs_drive = format!("{}{}", PREFIX, db);
let _ = process_lib::send_and_await_response(
&vfs_address,
false,
Some(serde_json::to_string(&kt::VfsRequest {
drive: vfs_drive.clone(),
action: kt::VfsAction::New,
}).unwrap()),
None,
None,
15,
).unwrap();
// (2)
let vfs_read = get_capability(
&vfs_address,
&make_vfs_cap("read", &vfs_drive),
).ok_or(anyhow::anyhow!("New failed: no vfs 'read' capability found"))?;
let vfs_write = get_capability(
&vfs_address,
&make_vfs_cap("write", &vfs_drive),
).ok_or(anyhow::anyhow!("New failed: no vfs 'write' capability found"))?;
let spawned_process_id = match spawn(
None,
"/sqlite_worker.wasm",
&OnPanic::None, // TODO: notify us
&Capabilities::Some(vec![vfs_read, vfs_write]),
false, // not public
) {
Ok(spawned_process_id) => spawned_process_id,
Err(e) => {
print_to_terminal(0, &format!("couldn't spawn: {}", e));
panic!("couldn't spawn"); // TODO
},
};
// grant caps
create_capability(&source.process, &make_db_cap("read", db));
create_capability(&source.process, &make_db_cap("write", db));
// initialize worker
send_request(
&Address {
node: our.node.clone(),
process: spawned_process_id.clone(),
},
&Request {
inherit: false,
expects_response: None,
ipc: ipc.clone(),
metadata: None,
},
None,
None,
);
// (4)
db_to_process.insert(db.into(), spawned_process_id);
// TODO: persistence?
send_response(
&Response {
inherit: false,
ipc,
metadata: None,
},
None,
);
},
sq::SqliteMessage::Write { ref db, ref statement } => {
let first_word = statement
.split_whitespace()
.next()
.map(|word| word.to_uppercase())
.unwrap_or("".to_string());
if !write_keywords.contains(&first_word) {
return Err(sq::SqliteError::NotAWriteKeyword.into())
}
forward_if_have_cap(our, "write", db, ipc, db_to_process)?;
},
sq::SqliteMessage::Read { ref db, ref query } => {
let first_word = query
.split_whitespace()
.next()
.map(|word| word.to_uppercase())
.unwrap_or("".to_string());
if !read_keywords.contains(&first_word) {
return Err(sq::SqliteError::NotAReadKeyword.into())
}
forward_if_have_cap(our, "read", db, ipc, db_to_process)?;
},
}
Ok(())
},
}
}
impl Guest for Component {
fn init(our: Address) {
print_to_terminal(0, "sqlite: begin");
let mut db_to_process: DbToProcess = HashMap::new();
let read_keywords: HashSet<String> = [
"ANALYZE",
"ATTACH",
"BEGIN",
"EXPLAIN",
"PRAGMA",
"SELECT",
"VALUES",
"WITH",
]
.iter()
.map(|x| x.to_string())
.collect();
let write_keywords: HashSet<String> = [
"ALTER",
"ANALYZE",
"COMMIT",
"CREATE",
"DELETE",
"DETACH",
"DROP",
"END",
"INSERT",
"REINDEX",
"RELEASE",
"RENAME",
"REPLACE",
"ROLLBACK",
"SAVEPOINT",
"UPDATE",
"VACUUM",
]
.iter()
.map(|x| x.to_string())
.collect();
loop {
match handle_message(&our, &mut db_to_process, &read_keywords, &write_keywords) {
Ok(()) => {},
Err(e) => {
print_to_terminal(0, format!(
"sqlite: error: {:?}",
e,
).as_str());
if let Some(e) = e.downcast_ref::<sq::SqliteError>() {
send_response(
&Response {
inherit: false,
ipc: Some(serde_json::to_string(&e).unwrap()),
metadata: None,
},
None,
);
}
},
};
}
}
}

View File

@ -0,0 +1 @@
../../../../src/process_lib.rs

View File

@ -0,0 +1 @@
../../sqlite_types.rs

View File

@ -0,0 +1,44 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub enum SqliteMessage {
New { db: String },
Write { db: String, statement: String },
Read { db: String, query: String },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SqlValue {
Integer(i64),
Real(f64),
Text(String),
Blob(Vec<u8>),
}
pub trait Deserializable: for<'de> Deserialize<'de> + Sized {
fn from_serialized(bytes: &[u8]) -> Result<Self, rmp_serde::decode::Error> {
rmp_serde::from_slice(bytes)
}
}
impl Deserializable for Vec<SqlValue> {}
impl Deserializable for Vec<Vec<SqlValue>> {}
#[derive(Debug, Serialize, Deserialize, thiserror::Error)]
pub enum SqliteError {
#[error("DbDoesNotExist")]
DbDoesNotExist,
#[error("DbAlreadyExists")]
DbAlreadyExists,
#[error("NoCap")]
NoCap,
#[error("RejectForeign")]
RejectForeign,
#[error("UnexpectedResponse")]
UnexpectedResponse,
#[error("NotAWriteKeyword")]
NotAWriteKeyword,
#[error("NotAReadKeyword")]
NotAReadKeyword,
}

627
modules/sqlite/sqlite_worker/Cargo.lock generated Normal file
View File

@ -0,0 +1,627 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ahash"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
]
[[package]]
name = "allocator-api2"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
[[package]]
name = "anyhow"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cargo-component-bindings"
version = "0.1.0"
source = "git+https://github.com/bytecodealliance/cargo-component#6a2996f280dd8671a2a2d3c83cbe09a39225b526"
dependencies = [
"cargo-component-macro",
"wit-bindgen",
]
[[package]]
name = "cargo-component-macro"
version = "0.1.0"
source = "git+https://github.com/bytecodealliance/cargo-component#6a2996f280dd8671a2a2d3c83cbe09a39225b526"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
"wit-bindgen-core",
"wit-bindgen-rust",
"wit-bindgen-rust-lib",
"wit-component",
]
[[package]]
name = "cc"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "fallible-iterator"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
[[package]]
name = "fallible-streaming-iterator"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "form_urlencoded"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
dependencies = [
"percent-encoding",
]
[[package]]
name = "hashbrown"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
dependencies = [
"ahash",
"allocator-api2",
]
[[package]]
name = "hashlink"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7"
dependencies = [
"hashbrown",
]
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "id-arena"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
[[package]]
name = "idna"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
dependencies = [
"equivalent",
"hashbrown",
"serde",
]
[[package]]
name = "itoa"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "leb128"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]]
name = "libc"
version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "libsqlite3-sys"
version = "0.26.0"
dependencies = [
"cc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "log"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "memchr"
version = "2.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
[[package]]
name = "num-traits"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "paste"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "percent-encoding"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
[[package]]
name = "pkg-config"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "proc-macro2"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "pulldown-cmark"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998"
dependencies = [
"bitflags 1.3.2",
"memchr",
"unicase",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rmp"
version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20"
dependencies = [
"byteorder",
"num-traits",
"paste",
]
[[package]]
name = "rmp-serde"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a"
dependencies = [
"byteorder",
"rmp",
"serde",
]
[[package]]
name = "rusqlite"
version = "0.29.0"
dependencies = [
"bitflags 2.4.0",
"fallible-iterator",
"fallible-streaming-iterator",
"hashlink",
"libsqlite3-sys",
"smallvec",
]
[[package]]
name = "ryu"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "semver"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
[[package]]
name = "serde"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "smallvec"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
[[package]]
name = "spdx"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b19b32ed6d899ab23174302ff105c1577e45a06b08d4fe0a9dd13ce804bbbf71"
dependencies = [
"smallvec",
]
[[package]]
name = "sqlite_worker"
version = "0.1.0"
dependencies = [
"anyhow",
"bincode",
"cargo-component-bindings",
"rmp-serde",
"rusqlite",
"serde",
"serde_json",
"thiserror",
"wit-bindgen",
]
[[package]]
name = "syn"
version = "2.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "unicase"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [
"version_check",
]
[[package]]
name = "unicode-bidi"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]]
name = "unicode-ident"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "url"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasm-encoder"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ba64e81215916eaeb48fee292f29401d69235d62d8b8fd92a7b2844ec5ae5f7"
dependencies = [
"leb128",
]
[[package]]
name = "wasm-metadata"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08dc59d1fa569150851542143ca79438ca56845ccb31696c70225c638e063471"
dependencies = [
"anyhow",
"indexmap",
"serde",
"serde_json",
"spdx",
"wasm-encoder",
"wasmparser",
]
[[package]]
name = "wasmparser"
version = "0.112.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e986b010f47fcce49cf8ea5d5f9e5d2737832f12b53ae8ae785bbe895d0877bf"
dependencies = [
"indexmap",
"semver",
]
[[package]]
name = "wit-bindgen"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8a3e8e965dc50e6eb4410d9a11720719fadc6a1713803ea5f3be390b81c8279"
dependencies = [
"bitflags 2.4.0",
"wit-bindgen-rust-macro",
]
[[package]]
name = "wit-bindgen-core"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77255512565dfbd0b61de466e854918041d1da53c7bc049d6188c6e02643dc1e"
dependencies = [
"anyhow",
"wit-component",
"wit-parser",
]
[[package]]
name = "wit-bindgen-rust"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "399c60e6ea8598d1380e792f13d557007834f0fb799fea6503408cbc5debb4ae"
dependencies = [
"anyhow",
"heck",
"wasm-metadata",
"wit-bindgen-core",
"wit-bindgen-rust-lib",
"wit-component",
]
[[package]]
name = "wit-bindgen-rust-lib"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd9fb7a43c7dc28b0b727d6ae01bf369981229b7539e768fba2b7a4df13feeeb"
dependencies = [
"heck",
"wit-bindgen-core",
]
[[package]]
name = "wit-bindgen-rust-macro"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44cea5ed784da06da0e55836a6c160e7502dbe28771c2368a595e8606243bf22"
dependencies = [
"anyhow",
"proc-macro2",
"syn",
"wit-bindgen-core",
"wit-bindgen-rust",
"wit-bindgen-rust-lib",
"wit-component",
]
[[package]]
name = "wit-component"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66d9f2d16dd55d1a372dcfd4b7a466ea876682a5a3cb97e71ec9eef04affa876"
dependencies = [
"anyhow",
"bitflags 2.4.0",
"indexmap",
"log",
"serde",
"serde_json",
"wasm-encoder",
"wasm-metadata",
"wasmparser",
"wit-parser",
]
[[package]]
name = "wit-parser"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61e8b849bea13cc2315426b16efe6eb6813466d78f5fde69b0bb150c9c40e0dc"
dependencies = [
"anyhow",
"id-arena",
"indexmap",
"log",
"pulldown-cmark",
"semver",
"unicode-xid",
"url",
]

View File

@ -0,0 +1,33 @@
[package]
name = "sqlite_worker"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[profile.release]
panic = "abort"
opt-level = "s"
lto = true
[dependencies]
anyhow = "1.0"
bincode = "1.3.3"
cargo-component-bindings = { git = "https://github.com/bytecodealliance/cargo-component" }
rmp-serde = "1.1"
rusqlite = { path = "../../../../rusqlite/", features = ["bundled", "wasm32-wasi-vfs"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0"
wit-bindgen = { version = "0.11.0", default_features = false }
[lib]
crate-type = ["cdylib"]
[package.metadata.component]
package = "component:uq-process"
[package.metadata.component.target]
path = "wit"
[package.metadata.component.dependencies]

View File

@ -0,0 +1,52 @@
#!/bin/bash
cd sqlite
cargo build --release --no-default-features --target wasm32-wasi
cd ../sqlite_worker
# Get special clang compiler required to build & link sqlite3 C lib.
mkdir -p target
cd target
WASI_VERSION=20
WASI_VERSION_FULL=${WASI_VERSION}.0
CC_PATH=$(realpath ./wasi-sdk-${WASI_VERSION_FULL}/bin/clang)
# Determine operating system
OS_TYPE="$(uname)"
if [ "$OS_TYPE" = "Darwin" ]; then
WASI_PLATFORM="macos"
elif [ "$OS_TYPE" = "Linux" ]; then
WASI_PLATFORM="linux"
else
echo "Unsupported OS: $OS_TYPE"
exit 1
fi
if [ ! -e "$CC_PATH" ]; then
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VERSION}/wasi-sdk-${WASI_VERSION_FULL}-${WASI_PLATFORM}.tar.gz
tar xvf wasi-sdk-${WASI_VERSION_FULL}-${WASI_PLATFORM}.tar.gz
fi
CC_PATH=$(realpath ./wasi-sdk-${WASI_VERSION_FULL}/bin/clang)
cd ..
# We write env vars to `.cargo/config.toml` here because:
# 1. Doing `export foo=/path && export bar=/path2 && RUSTFLAGS=baz cargo build ...`
# does not properly pass the RUSTFLAGS (cargo bug?).
# 2. Specifying `~/path` inside `.cargo/config.toml` doesn't expand.
mkdir -p .cargo
# CC_PATH=$(realpath ~/wasi-sdk/wasi-sdk-20.0/bin/clang)
# Write to the .cargo/config.toml file
cat <<EOF > .cargo/config.toml
[env]
CC_wasm32_wasi = "$CC_PATH"
CARGO_TARGET_WASM32_WASI_LINKER = "$CC_PATH"
EOF
RUSTFLAGS="-C target-feature=-crt-static -C link-arg=-Wl,--no-entry,--export=init,--export=cabi_realloc" cargo build --release --no-default-features --target wasm32-wasi

View File

@ -0,0 +1 @@
../../../../src/kernel_types.rs

View File

@ -0,0 +1,469 @@
cargo_component_bindings::generate!();
use core::ffi::{c_char, c_int, c_ulonglong, CStr};
use std::ffi::CString;
use crate::sqlite_types::Deserializable;
use rusqlite::{types::FromSql, types::FromSqlError, types::ToSql, types::ValueRef};
// use serde::{Deserialize, Serialize};
use bindings::component::uq_process::types::*;
use bindings::{get_payload, Guest, print_to_terminal, receive, send_and_await_response, send_response};
mod kernel_types;
use kernel_types as kt;
mod process_lib;
mod sqlite_types;
use sqlite_types as sq;
struct Component;
const PREFIX: &str = "sqlite-";
impl ToSql for sq::SqlValue {
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput> {
match self {
sq::SqlValue::Integer(i) => i.to_sql(),
sq::SqlValue::Real(f) => f.to_sql(),
sq::SqlValue::Text(ref s) => s.to_sql(),
sq::SqlValue::Blob(ref b) => b.to_sql(),
}
}
}
impl FromSql for sq::SqlValue {
fn column_result(value: ValueRef<'_>) -> Result<Self, FromSqlError> {
match value {
ValueRef::Integer(i) => Ok(sq::SqlValue::Integer(i)),
ValueRef::Real(f) => Ok(sq::SqlValue::Real(f)),
ValueRef::Text(t) => {
let text_str = std::str::from_utf8(t).map_err(|_| FromSqlError::InvalidType)?;
Ok(sq::SqlValue::Text(text_str.to_string()))
},
ValueRef::Blob(b) => Ok(sq::SqlValue::Blob(b.to_vec())),
_ => Err(FromSqlError::InvalidType),
}
}
}
#[repr(C)]
pub struct CPreOptionStr {
is_empty: c_int, // 0 -> string is empty
string: CString,
}
#[repr(C)]
pub struct COptionStr {
is_empty: c_int, // 0 -> string is empty
string: *mut c_char,
}
#[repr(C)]
struct CBytes {
data: *mut u8,
len: usize,
}
#[repr(C)]
pub struct CPayload {
is_empty: c_int, // 0 -> payload is empty
mime: *mut COptionStr,
bytes: *mut CBytes,
}
#[repr(C)]
pub struct CPrePayload {
is_empty: c_int, // 0 -> payload is empty
mime: COptionStr,
bytes: CBytes,
}
#[repr(C)]
pub struct CProcessId {
process_name: *const c_char,
package_name: *const c_char,
publisher_node: *const c_char,
}
#[repr(C)]
pub struct CIpcMetadata {
ipc: *mut COptionStr,
metadata: *mut COptionStr,
}
impl CPreOptionStr {
fn new(s: Option<String>) -> Self {
let (is_empty, string) = match s {
None => (0, CString::new("").unwrap()),
Some(s) => (1, CString::new(s).unwrap()),
};
CPreOptionStr {
is_empty,
string,
}
}
}
impl COptionStr {
fn new(s: Option<String>) -> Self {
let (is_empty, string) = match s {
None => (0, CString::new("").unwrap()),
Some(s) => (1, CString::new(s).unwrap()),
};
COptionStr {
is_empty,
string: string.as_ptr() as *mut c_char,
}
}
}
fn from_coptionstr_to_option_string(s: *const COptionStr) -> Option<String> {
if unsafe { (*s).is_empty == 0 } {
None
} else {
Some(from_cstr_to_string(unsafe { (*s).string }))
}
}
impl CBytes {
fn new(mut bytes: Vec<u8>) -> Self {
CBytes {
data: bytes.as_mut_ptr(),
len: bytes.len(),
}
}
fn new_empty() -> Self {
CBytes::new(Vec::with_capacity(0))
}
}
impl From<Vec<u8>> for CBytes {
fn from(bytes: Vec<u8>) -> Self {
CBytes::new(bytes)
}
}
impl From<CBytes> for Vec<u8> {
fn from(bytes: CBytes) -> Self {
let bytes = unsafe { Vec::from_raw_parts(bytes.data, bytes.len, bytes.len) };
bytes
}
}
fn from_cbytes_to_vec_u8(bytes: *mut CBytes) -> Vec<u8> {
// let bytes = unsafe { Vec::from_raw_parts((*bytes).data, (*bytes).len, (*bytes).len) };
let bytes = unsafe { std::slice::from_raw_parts((*bytes).data, (*bytes).len) };
let bytes = bytes.to_vec();
bytes
}
impl From<Option<Payload>> for CPrePayload {
fn from(p: Option<Payload>) -> Self {
let (is_empty, mime, bytes) = match p {
None => (0, COptionStr::new(None), CBytes::new_empty()),
Some(Payload { mime, bytes }) => (1, COptionStr::new(mime), CBytes::new(bytes)),
};
CPrePayload {
is_empty,
mime,
bytes,
}
}
}
impl From<CPayload> for Option<Payload> {
fn from(p: CPayload) -> Self {
if p.is_empty == 0 {
None
} else {
let mime = from_coptionstr_to_option_string(p.mime);
let bytes = from_cbytes_to_vec_u8(p.bytes);
Some(Payload {
mime,
bytes,
})
}
}
}
fn from_cpayload_to_option_payload(p: *const CPayload) -> Option<Payload> {
if unsafe { (*p).is_empty == 0 } {
None
} else {
let mime = unsafe { from_coptionstr_to_option_string((*p).mime) };
let bytes = unsafe { from_cbytes_to_vec_u8((*p).bytes) };
Some(Payload {
mime,
bytes,
})
}
}
fn from_cprocessid_to_processid(pid: *const CProcessId) -> ProcessId {
ProcessId {
process_name: from_cstr_to_string(unsafe { (*pid).process_name }),
package_name: from_cstr_to_string(unsafe { (*pid).package_name }),
publisher_node: from_cstr_to_string(unsafe { (*pid).publisher_node }),
}
}
fn from_cstr_to_string(s: *const c_char) -> String {
let cstr = unsafe { CStr::from_ptr(s) };
cstr.to_str().unwrap().into()
}
#[no_mangle]
pub extern "C" fn get_payload_wrapped(return_val: *mut CPayload) {
// TODO: remove this logic; just here to avoid writing to invalid places
// in memory due to an fs bug where chunk size may be bigger than requested
let max_len = unsafe { (*(*return_val).bytes).len.clone() };
let payload = get_payload();
let mime_len = {
match payload {
None => None,
Some(ref payload) => {
match payload.mime {
None => None,
Some(ref mime) => {
Some(mime.len())
},
}
}
}
};
unsafe {
match payload {
None => {},
Some(payload) => {
(*return_val).is_empty = 1;
match payload.mime {
None => {},
Some(mime) => {
(*(*return_val).mime).is_empty = 1;
let Some(mime_len) = mime_len else { panic!("") };
let mime = CString::new(mime).unwrap();
std::ptr::copy_nonoverlapping(
mime.as_ptr(),
(*(*return_val).mime).string,
mime_len + 1,
);
},
}
(*(*return_val).bytes).len = std::cmp::min(max_len, payload.bytes.len());
std::ptr::copy_nonoverlapping(
payload.bytes.as_ptr(),
(*(*return_val).bytes).data,
std::cmp::min(max_len, payload.bytes.len()),
);
},
}
}
}
impl CIpcMetadata {
fn copy_to_ptr(ptr: *mut CIpcMetadata, ipc: CPreOptionStr, metadata: CPreOptionStr) {
unsafe {
(*(*ptr).ipc).is_empty = ipc.is_empty;
if ipc.is_empty == 1 {
std::ptr::copy_nonoverlapping(
ipc.string.as_ptr(),
(*(*ptr).ipc).string,
ipc.string.as_bytes_with_nul().len(),
);
}
(*(*ptr).metadata).is_empty = metadata.is_empty;
if metadata.is_empty == 1 {
std::ptr::copy_nonoverlapping(
metadata.string.as_ptr(),
(*(*ptr).metadata).string,
metadata.string.as_bytes_with_nul().len(),
);
}
}
}
}
#[no_mangle]
pub extern "C" fn send_and_await_response_wrapped(
target_node: *const c_char,
target_process: *const CProcessId,
request_ipc: *const COptionStr,
request_metadata: *const COptionStr,
payload: *const CPayload,
timeout: c_ulonglong,
return_val: *mut CIpcMetadata,
) {
let target_node = from_cstr_to_string(target_node);
let target_process = from_cprocessid_to_processid(target_process);
let payload = from_cpayload_to_option_payload(payload);
let request_ipc = from_coptionstr_to_option_string(request_ipc);
let request_metadata = from_coptionstr_to_option_string(request_metadata);
let (
_,
Message::Response((Response { ipc, metadata, .. }, _)),
) = send_and_await_response(
&Address {
node: target_node,
process: target_process,
},
&Request {
inherit: false,
expects_response: Some(timeout),
ipc: request_ipc,
metadata: request_metadata,
},
match payload {
None => None,
Some(ref p) => Some(p),
},
).unwrap() else {
panic!("");
};
let ipc = CPreOptionStr::new(ipc);
let metadata = CPreOptionStr::new(metadata);
CIpcMetadata::copy_to_ptr(return_val, ipc, metadata);
}
fn handle_message (
our: &Address,
db_handle: &mut Option<rusqlite::Connection>,
) -> anyhow::Result<()> {
let (source, message) = receive().unwrap();
// let (source, message) = receive()?;
if our.node != source.node {
return Err(sq::SqliteError::RejectForeign.into());
}
match message {
Message::Response(_) => { unimplemented!() },
Message::Request(Request { ipc, .. }) => {
match process_lib::parse_message_ipc(ipc.clone())? {
sq::SqliteMessage::New { db } => {
let vfs_address = Address {
node: our.node.clone(),
process: kt::ProcessId::new("vfs", "sys", "uqbar").en_wit(),
};
let vfs_drive = format!("{}{}", PREFIX, db);
match db_handle {
Some(_) => {
return Err(sq::SqliteError::DbAlreadyExists.into());
},
None => {
let flags = rusqlite::OpenFlags::default();
*db_handle = Some(rusqlite::Connection::open_with_flags_and_vfs(
format!(
"{}:{}:/{}.sql",
our.node,
vfs_drive,
db,
),
flags,
"uqbar",
)?);
},
}
},
sq::SqliteMessage::Write { ref statement, .. } => {
let Some(db_handle) = db_handle else {
return Err(sq::SqliteError::DbDoesNotExist.into());
};
match get_payload() {
None => {
let parameters: Vec<&dyn rusqlite::ToSql> = vec![];
db_handle.execute(
statement,
&parameters[..],
)?;
},
Some(Payload { mime: _, ref bytes }) => {
let parameters = Vec::<sq::SqlValue>::from_serialized(&bytes)?;
let parameters: Vec<&dyn rusqlite::ToSql> = parameters
.iter()
.map(|param| param as &dyn rusqlite::ToSql)
.collect();
db_handle.execute(
statement,
&parameters[..],
)?;
},
}
send_response(
&Response {
inherit: false,
ipc,
metadata: None,
},
None,
);
},
sq::SqliteMessage::Read { ref query, .. } => {
let Some(db_handle) = db_handle else {
return Err(sq::SqliteError::DbDoesNotExist.into());
};
let mut statement = db_handle.prepare(query)?;
let column_names: Vec<String> = statement
.column_names()
.iter()
.map(|c| c.to_string())
.collect();
let number_columns = column_names.len();
let results: Vec<Vec<sq::SqlValue>> = statement
.query_map([], |row| {
(0..number_columns)
.map(|i| row.get(i))
.collect()
})?
.map(|item| item.unwrap()) // TODO
.collect();
let results = rmp_serde::to_vec(&results).unwrap();
send_response(
&Response {
inherit: false,
ipc,
metadata: None,
},
Some(&Payload {
mime: None,
bytes: results,
}),
);
},
}
Ok(())
},
}
}
impl Guest for Component {
fn init(our: Address) {
print_to_terminal(1, "sqlite_worker: begin");
let mut db_handle: Option<rusqlite::Connection> = None;
loop {
match handle_message(&our, &mut db_handle) {
Ok(()) => {},
Err(e) => {
// TODO: should we send an error on failure?
print_to_terminal(0, format!(
"sqlite_worker: error: {:?}",
e,
).as_str());
},
};
}
}
}

View File

@ -0,0 +1 @@
../../../../src/process_lib.rs

View File

@ -0,0 +1 @@
../../sqlite_types.rs

View File

@ -298,6 +298,7 @@ pub enum VfsError {
BadDriveName,
BadDescriptor,
NoCap,
EntryNotFound,
}
#[allow(dead_code)]
@ -307,6 +308,7 @@ impl VfsError {
VfsError::BadDriveName => "BadDriveName",
VfsError::BadDescriptor => "BadDescriptor",
VfsError::NoCap => "NoCap",
VfsError::EntryNotFound => "EntryNotFound",
}
}
}

View File

@ -638,6 +638,7 @@ pub enum VfsError {
BadDriveName,
BadDescriptor,
NoCap,
EntryNotFound,
}
#[allow(dead_code)]
@ -647,6 +648,7 @@ impl VfsError {
VfsError::BadDriveName => "BadDriveName",
VfsError::BadDescriptor => "BadDescriptor",
VfsError::NoCap => "NoCap",
VfsError::EntryNotFound => "EntryNotFound",
}
}
}

View File

@ -1096,7 +1096,7 @@ async fn match_request(
})
.await
.unwrap();
panic!("");
return Err(VfsError::EntryNotFound);
};
let Some(mut entry) = vfs.key_to_entry.remove(&key) else {
send_to_terminal
@ -1106,7 +1106,7 @@ async fn match_request(
})
.await
.unwrap();
panic!("");
return Err(VfsError::EntryNotFound);
};
match entry.entry_type {
EntryType::Dir { .. } => {
@ -1158,7 +1158,7 @@ async fn match_request(
})
.await
.unwrap();
panic!("");
return Err(VfsError::EntryNotFound);
};
let Some(entry) = vfs.key_to_entry.remove(&key) else {
send_to_terminal
@ -1168,7 +1168,7 @@ async fn match_request(
})
.await
.unwrap();
panic!("");
return Err(VfsError::EntryNotFound);
};
match entry.entry_type {
EntryType::Dir {
@ -1226,7 +1226,7 @@ async fn match_request(
let file_hash = {
let mut vfs = vfs.lock().await;
let Some(key) = vfs.path_to_key.remove(&full_path) else {
panic!("");
return Err(VfsError::EntryNotFound);
};
let key2 = key.clone();
let Key::File { id: file_hash } = key2 else {
@ -1280,7 +1280,7 @@ async fn match_request(
let file_hash = {
let mut vfs = vfs.lock().await;
let Some(key) = vfs.path_to_key.remove(&full_path) else {
panic!(""); // TODO
return Err(VfsError::EntryNotFound);
};
let key2 = key.clone();
let Key::File { id: file_hash } = key2 else {
@ -1350,12 +1350,16 @@ async fn match_request(
}
VfsAction::GetHash(full_path) => {
let vfs = vfs.lock().await;
let mut ipc = Some(serde_json::to_string(&VfsResponse::GetHash(None)).unwrap());
if let Some(key) = vfs.path_to_key.get(&full_path) {
if let Key::File { id: hash } = key {
ipc = Some(serde_json::to_string(&VfsResponse::GetHash(Some(*hash))).unwrap());
};
}
let Some(key) = vfs.path_to_key.get(&full_path) else {
return Err(VfsError::EntryNotFound);
};
let ipc = Some(
serde_json::to_string(&VfsResponse::GetHash(match key {
Key::File { id } => Some(id.clone()),
Key::Dir { .. } => None,
}))
.unwrap(),
);
(ipc, None)
}
VfsAction::GetEntry(ref full_path) => {
@ -1404,14 +1408,10 @@ async fn match_request(
}
};
let entry_not_found = (
Some(serde_json::to_string(&VfsResponse::Err(VfsError::BadDescriptor)).unwrap()),
None,
);
match key {
None => entry_not_found,
None => return Err(VfsError::EntryNotFound),
Some(key) => match entry {
None => entry_not_found,
None => return Err(VfsError::EntryNotFound),
Some(entry) => match entry.entry_type {
EntryType::Dir {
parent: _,
@ -1501,7 +1501,7 @@ async fn match_request(
let file_hash = {
let mut vfs = vfs.lock().await;
let Some(key) = vfs.path_to_key.remove(full_path) else {
panic!(""); // TODO
return Err(VfsError::EntryNotFound);
};
let key2 = key.clone();
let Key::File { id: file_hash } = key2 else {
@ -1575,7 +1575,7 @@ async fn match_request(
let file_hash = {
let mut vfs = vfs.lock().await;
let Some(key) = vfs.path_to_key.remove(full_path) else {
panic!("");
return Err(VfsError::EntryNotFound);
};
let key2 = key.clone();
let Key::File { id: file_hash } = key2 else {