{"id":16866998,"url":"https://github.com/thomasdezeeuw/a10","last_synced_at":"2025-11-05T04:30:31.730Z","repository":{"id":84262611,"uuid":"386929179","full_name":"Thomasdezeeuw/a10","owner":"Thomasdezeeuw","description":"Library safely exposing the io_uring API.","archived":false,"fork":false,"pushed_at":"2024-08-17T08:50:54.000Z","size":796,"stargazers_count":53,"open_issues_count":19,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-14T14:52:26.954Z","etag":null,"topics":["iouring","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Thomasdezeeuw.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-17T12:14:47.000Z","updated_at":"2024-10-14T04:31:29.000Z","dependencies_parsed_at":"2024-06-08T12:38:10.506Z","dependency_job_id":"5bf163b7-09c4-4d3e-909f-7df5a7bed1a5","html_url":"https://github.com/Thomasdezeeuw/a10","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Thomasdezeeuw%2Fa10","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Thomasdezeeuw%2Fa10/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Thomasdezeeuw%2Fa10/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Thomasdezeeuw%2Fa10/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Thomasdezeeuw","download_url":"https://codeload.github.com/Thomasdezeeuw/a10/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239449586,"owners_count":19640535,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["iouring","rust"],"created_at":"2024-10-13T14:52:21.681Z","updated_at":"2025-11-05T04:30:31.699Z","avatar_url":"https://github.com/Thomasdezeeuw.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# A10\n\nThe [A10] io\\_uring library.\n\nThis library is meant as a low-level library safely exposing the io\\_uring API.\nFor simplicity this only has two main types and a number of helper types:\n * `Ring` is a wrapper around io\\_uring used to poll for completion events.\n * `AsyncFd` is a wrapper around a file descriptor that provides a safe API to\n   schedule operations.\n\n[A10]: https://en.wikipedia.org/wiki/A10_motorway_(Netherlands)\n\n## Linux Required\n\nCurrently this requires a fairly new Linux kernel version, everything should\nwork on Linux v6.1 and up.\n\n## Examples\n\nA10 is expected to be integrated into a `Future` runtime, but it can work as a\nstand-alone library.\n\n```rust\nuse std::future::Future;\nuse std::io;\nuse std::path::PathBuf;\n\nuse a10::{AsyncFd, Extract, Ring, SubmissionQueue};\n\nfn main() -\u003e io::Result\u003c()\u003e {\n    // Create a new I/O uring supporting 8 submission entries.\n    let mut ring = Ring::new(8)?;\n\n    // Get access to the submission queue, used to... well queue submissions.\n    let sq = ring.submission_queue().clone();\n    // A10 makes use of `Future`s to represent the asynchronous nature of\n    // io_uring.\n    let future = cat(sq, \"./src/lib.rs\");\n\n    // This `block_on` function would normally be implement by a `Future`\n    // runtime, but we show a simple example implementation below.\n    block_on(\u0026mut ring, future)\n}\n\n/// A \"cat\" like function, which reads from `filename` and writes it to\n/// standard out.\nasync fn cat(sq: SubmissionQueue, filename: \u0026str) -\u003e io::Result\u003c()\u003e {\n    // Because io_uring uses asychronous operation it needs access to the\n    // path for the duration the operation is active. To prevent use-after\n    // free and similar issues we need ownership of the arguments. In the\n    // case of opening a file it means we need ownership of the file name.\n    let filename = PathBuf::from(filename);\n    // Open a file for reading.\n    let file: AsyncFd = a10::fs::OpenOptions::new().open(sq.clone(), filename).await?;\n\n    // Next we'll read from the from the file.\n    // Here we need ownership of the buffer, same reason as discussed above.\n    let buf = file.read(Vec::with_capacity(32 * 1024)).await?;\n\n    // Let's write what we read from the file to standard out.\n    let stdout = a10::io::stdout(sq);\n    // For writing we also need ownership of the buffer, so we move the\n    // buffer into function call. However by default we won't get it back,\n    // to match the API you see in the standard libray.\n    // But using buffers just once it a bit wasteful, so we can it back\n    // using the `Extract` trait (the call to `extract`). It changes the\n    // return values (and `Future` type) to return the buffer and the amount\n    // of bytes written.\n    let (buf, n) = stdout.write(buf).extract().await?;\n\n    // All done.\n    Ok(())\n}\n\n/// Block on the `future`, expecting polling `ring` to drive it forward.\nfn block_on\u003cFut, T\u003e(ring: \u0026mut Ring, future: Fut) -\u003e Fut::Output\nwhere\n    Fut: Future\u003cOutput = io::Result\u003cT\u003e\u003e,\n{\n    use std::ptr;\n    use std::task::{self, Poll, RawWaker, RawWakerVTable};\n\n    // Pin the future to the stack so we don't move it around.\n    let mut future = std::pin::pin!(future);\n\n    // Create a task context to poll the future work.\n    let waker = unsafe { task::Waker::from_raw(RawWaker::new(ptr::null(), \u0026WAKER_VTABLE)) };\n    let mut ctx = task::Context::from_waker(\u0026waker);\n\n    loop {\n        match future.as_mut().poll(\u0026mut ctx) {\n            Poll::Ready(result) =\u003e return result,\n            Poll::Pending =\u003e {\n                // Poll the `Ring` to get an update on the operation(s).\n                //\n                // In pratice you would first yield to another future, but\n                // in this example we don't have one, so we'll always poll\n                // the `Ring`.\n                ring.poll(None)?;\n            }\n        }\n    }\n\n    // A waker implementation that does nothing.\n    static WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(\n        |_| RawWaker::new(ptr::null(), \u0026WAKER_VTABLE),\n        |_| {},\n        |_| {},\n        |_| {},\n    );\n}\n```\n\nFor more examples see the [examples directory].\n\n[examples directory]: ./examples\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomasdezeeuw%2Fa10","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthomasdezeeuw%2Fa10","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomasdezeeuw%2Fa10/lists"}