The first running test

This commit is contained in:
soup 2024-10-19 14:14:16 -04:00
parent d740216b1d
commit f2f668331d
No known key found for this signature in database
12 changed files with 586 additions and 13 deletions

140
Cargo.lock generated Normal file
View file

@ -0,0 +1,140 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "async-channel"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
dependencies = [
"concurrent-queue",
"event-listener-strategy",
"futures-core",
"pin-project-lite",
]
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "concurrent-queue"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "event-listener"
version = "5.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba"
dependencies = [
"concurrent-queue",
"parking",
"pin-project-lite",
]
[[package]]
name = "event-listener-strategy"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1"
dependencies = [
"event-listener",
"pin-project-lite",
]
[[package]]
name = "fastrand"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
[[package]]
name = "futures-core"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-io"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
[[package]]
name = "futures-lite"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5"
dependencies = [
"fastrand",
"futures-core",
"futures-io",
"parking",
"pin-project-lite",
]
[[package]]
name = "io-uring"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9c844e08c94e8558389fb9b8944cb99fc697e231c975e4274b42bc99e0625b"
dependencies = [
"bitflags",
"cfg-if",
"libc",
]
[[package]]
name = "libc"
version = "0.2.161"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
[[package]]
name = "parking"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "pollster"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2"
[[package]]
name = "wove"
version = "0.0.0"
dependencies = [
"async-channel",
"futures-lite",
"io-uring",
"libc",
"pollster",
]

View file

@ -1,8 +1,18 @@
[package]
name = "o_o"
version = "0.1.0"
name = "wove"
version = "0.0.0"
edition = "2021"
description = "An async runtime"
license = "AGPL"
description = "wove"
license = "AGPL-3.0-or-later"
[dependencies]
[dev-dependencies]
pollster = { version = "0.3.0" }
futures-lite = { version = "2.3.0" }
[target.'cfg(target_os = "linux")'.dependencies]
io-uring = { version = '0.7.1' }
libc = { version = "0.2.161" }
async-channel = { version = "2.3.1" }

165
flake.lock Normal file
View file

@ -0,0 +1,165 @@
{
"nodes": {
"crane": {
"locked": {
"lastModified": 1729273024,
"narHash": "sha256-Mb5SemVsootkn4Q2IiY0rr9vrXdCCpQ9HnZeD/J3uXs=",
"owner": "ipetkov",
"repo": "crane",
"rev": "fa8b7445ddadc37850ed222718ca86622be01967",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"deno-flake": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 0,
"narHash": "sha256-RsFYFS4k28JneAcEQO8ITXqIXKyBIa8FIKEPfz3NJHA=",
"type": "git",
"url": "file:///home/n/src/deno-flake"
},
"original": {
"type": "git",
"url": "file:///home/n/src/deno-flake"
}
},
"fenix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1728973961,
"narHash": "sha256-Jkqaw9O7WXTf5SHrK7xr9HpVU/mEPVg0Sp6s3AENC90=",
"owner": "nix-community",
"repo": "fenix",
"rev": "d6a9ff4d1e60c347a23bc96ccdb058d37a810541",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "fenix",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1726560853,
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1726560853,
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1725930920,
"narHash": "sha256-RVhD9hnlTT2nJzPHlAqrWqCkA7T6CYrP41IoVRkciZM=",
"path": "/nix/store/20yis5w6g397plssim663hqxdiiah2wr-source",
"rev": "44a71ff39c182edaf25a7ace5c9454e7cba2c658",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"crane": "crane",
"deno-flake": "deno-flake",
"fenix": "fenix",
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs"
}
},
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1728921748,
"narHash": "sha256-BOCZ5osPOMh2BPHnkK4sVdTGj7sn47rBn1nxjrzWe5U=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "0319586ef2a2636f6d6b891690b7ebebf4337c85",
"type": "github"
},
"original": {
"owner": "rust-lang",
"ref": "nightly",
"repo": "rust-analyzer",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

38
flake.nix Normal file
View file

@ -0,0 +1,38 @@
{
inputs.nixpkgs.url = "nixpkgs";
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.deno-flake = {
url = "git+file:///home/n/src/deno-flake";
inputs.nixpkgs.follows = "nixpkgs";
};
inputs.fenix = {
url = "github:nix-community/fenix";
inputs.nixpkgs.follows = "nixpkgs";
};
inputs.crane = {
url = "github:ipetkov/crane";
inputs.nixpkgs.follows = "nixpkgs";
};
outputs = i:
i.flake-utils.lib.eachDefaultSystem (system:
let
pkgs = i.nixpkgs.legacyPackages.${system};
pkgsDeno = i.deno-flake.packages.${system};
pkgsFenix = i.fenix.packages.${system};
minimal = pkgsFenix.minimal;
complete = pkgsFenix.complete;
stable = pkgsFenix.stable;
in {
devShells.default = pkgs.mkShell {
packages = [
(pkgsFenix.combine [
(complete.withComponents [ "rust-src" "rust-analyzer" "rustfmt" "clippy" ])
(minimal.withComponents [ "cargo" "rustc" "rust-std" ])
])
pkgs.cargo-watch
];
};
});
}

5
rustfmt.toml Normal file
View file

@ -0,0 +1,5 @@
edition = "2021"
hard_tabs = true
match_block_trailing_comma = true
max_width = 95
empty_item_single_line = false

1
src/aliases.rs Normal file
View file

@ -0,0 +1 @@
pub type IoResult<T> = std::io::Result<T>;

21
src/fs.rs Normal file
View file

@ -0,0 +1,21 @@
use std::path::PathBuf;
use crate::{aliases::IoResult, plat::Platform, Wove};
pub async fn read_to_string(wove: &Wove, path: PathBuf) -> IoResult<String> {
let mut file = wove.platform.open_file(path).await?;
let mut out = Vec::new();
loop {
let buf = vec![0; 4096].into_boxed_slice();
let buf = wove.platform.read(&mut file, out.len(), buf).await?;
dbg!(buf.len());
if buf.len() == 0 {
break;
}
out.extend_from_slice(&buf);
}
String::from_utf8(out).map_err(std::io::Error::other)
}

View file

@ -1,14 +1,57 @@
pub fn add(left: u64, right: u64) -> u64 {
left + right
#![feature(async_closure)]
mod aliases;
pub mod fs;
pub mod net;
mod plat;
mod wove;
use aliases::IoResult;
#[cfg(target_os = "linux")]
pub use plat::linux::PlatformLinux as PlatImpl;
use plat::Platform;
pub struct Wove {
platform: PlatImpl,
}
impl Wove {
pub fn new() -> IoResult<Self> {
Ok(Self {
platform: PlatImpl::new(Default::default())?,
})
}
pub async fn run(&self) -> IoResult<()> {
loop {
self.platform.tick().await?;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
mod test {
use std::path::PathBuf;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
use crate::Wove;
#[test]
fn sketch() {
let mut wove = Wove::new().unwrap();
let wove = &mut wove;
let fut = async {
let run = async {
wove.run().await?;
Ok("".to_string())
};
let contents = crate::fs::read_to_string(wove, PathBuf::from("src/lib.rs"));
let contents = futures_lite::future::race(run, contents).await;
contents
};
let out = pollster::block_on(fut).unwrap();
assert_eq!(out, "");
}
}

1
src/net.rs Normal file
View file

@ -0,0 +1 @@

124
src/plat/linux.rs Normal file
View file

@ -0,0 +1,124 @@
use std::{ffi::CString, future::Future, path::PathBuf, pin::Pin};
use io_uring::IoUring;
use crate::aliases::IoResult;
use super::Platform;
pub type CallbackFuture = Pin<Box<dyn Future<Output = ()> + 'static>>;
pub type Callback = Box<dyn FnOnce(io_uring::cqueue::Entry) -> CallbackFuture + 'static>;
fn box_callback_as_u64(callback: impl async FnOnce(io_uring::cqueue::Entry) + 'static) -> u64 {
let bx: Callback = Box::new(move |entry| Box::pin(callback(entry)));
let bx: Box<Callback> = Box::new(bx);
let leaked = Box::leak(bx);
let ptr = leaked as *mut _;
ptr as u64
}
unsafe fn u64_as_callback(v: u64) -> Box<Callback> {
let v = v as *mut Callback;
unsafe { Box::from_raw(v) }
}
pub struct PlatformLinux {
uring: io_uring::IoUring,
tx_should_tick: async_channel::Sender<()>,
rx_should_tick: async_channel::Receiver<()>,
_pd: core::marker::PhantomData<std::rc::Rc<()>>,
}
impl PlatformLinux {
fn set_should_tick(&self) {
self.tx_should_tick.force_send(()).unwrap();
}
async fn wait_tick(&self) {
self.rx_should_tick.recv().await.unwrap()
}
}
impl Platform for PlatformLinux {
type NewOptions = ();
type FileHandle = io_uring::types::Fd;
fn new(opts: Self::NewOptions) -> IoResult<Self> {
let (tx_should_tick, rx_should_tick) = async_channel::bounded(1);
Ok(Self {
uring: IoUring::new(256)?,
tx_should_tick,
rx_should_tick,
_pd: Default::default(),
})
}
async fn tick(&self) -> IoResult<()> {
self.wait_tick().await;
self.uring.submit()?;
let cq = unsafe { self.uring.completion_shared() };
for entry in cq {
let cb = unsafe { u64_as_callback(entry.user_data()) };
cb(entry).await;
}
Ok(())
}
async fn open_file(&self, path: PathBuf) -> IoResult<Self::FileHandle> {
let (tx, rx) = async_channel::bounded(1);
let path = CString::new(path.into_os_string().into_encoded_bytes())?;
let entry =
io_uring::opcode::OpenAt::new(io_uring::types::Fd(libc::AT_FDCWD), path.as_ptr())
.build()
.user_data(box_callback_as_u64(async move |entry| {
let fd = entry.result();
let fd = io_uring::types::Fd(fd);
tx.send(fd).await.unwrap();
std::mem::drop(path);
}));
unsafe {
self.uring.submission_shared().push(&entry).unwrap();
}
self.set_should_tick();
Ok(rx.recv().await.unwrap())
}
async fn read(
&self,
f: &mut Self::FileHandle,
offset: usize,
mut buf: Box<[u8]>,
) -> IoResult<Box<[u8]>> {
let (tx, rx) = async_channel::bounded(1);
let entry = io_uring::opcode::Read::new(*f, buf.as_mut_ptr(), buf.len() as _)
.offset(offset as _)
.build()
.user_data(box_callback_as_u64(async move |entry| {
let read_amt = entry.result();
dbg!(read_amt);
let mut buf = buf.into_vec();
buf.truncate(read_amt as _);
tx.send(buf.into_boxed_slice()).await.unwrap()
}));
unsafe {
self.uring.submission_shared().push(&entry).unwrap();
}
self.set_should_tick();
Ok(rx.recv().await.unwrap())
}
}

24
src/plat/mod.rs Normal file
View file

@ -0,0 +1,24 @@
use std::path::PathBuf;
use crate::aliases::IoResult;
pub(crate) mod linux;
pub trait Platform {
type NewOptions: Default;
type FileHandle;
fn new(opts: Self::NewOptions) -> IoResult<Self>
where
Self: Sized;
async fn tick(&self) -> IoResult<()>;
async fn open_file(&self, path: PathBuf) -> IoResult<Self::FileHandle>;
async fn read(
&self,
f: &mut Self::FileHandle,
offset: usize,
buf: Box<[u8]>,
) -> IoResult<Box<[u8]>>;
}

1
src/wove.rs Normal file
View file

@ -0,0 +1 @@