From 2bf31317753b242bedec37a0a6a576f5c26533c7 Mon Sep 17 00:00:00 2001 From: Bruno Tavares Date: Wed, 26 Feb 2020 19:45:26 -0300 Subject: [PATCH 1/2] Implement async API for random-access-storage This commit moves the API from a sync call into async functions using async_trait. We would like to use async operations on hypercore, and it would be nice to have the underlying storage using async-io when possible. As discussed on https://github.com/datrs/hypercore/issues/97, we could change the API to use async functions on the 'ram' trait. Async Trait methods are still unstable, but possible using the 'async-trait' crate through a macro. This PR moves the API to use async-fns. Tests are passing. --- .travis.yml | 11 +++++------ Cargo.toml | 2 ++ README.md | 24 ++++++++++++------------ src/lib.rs | 29 ++++++++++++++++++----------- 4 files changed, 37 insertions(+), 29 deletions(-) diff --git a/.travis.yml b/.travis.yml index e73fe7d..153c991 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,13 @@ language: rust rust: - - nightly + - stable before_script: | - rustup update stable && - rustup component add --toolchain stable rustfmt-preview && - rustup component add --toolchain stable clippy-preview + rustup component add rustfmt && + rustup component add clippy script: | - cargo +stable fmt -- --check && - cargo +stable clippy -- -D clippy::all && + cargo fmt -- --check && + cargo clippy -- -D clippy::all && cargo build --verbose && cargo test --verbose cache: cargo \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 0dc6f8f..cb5cb0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,5 @@ readme = "README.md" edition = "2018" [dependencies] +async-trait = "0.1.24" +futures = "0.3.4" diff --git a/README.md b/README.md index 0740f5d..52211f7 100644 --- a/README.md +++ b/README.md @@ -14,52 +14,52 @@ can easily be swapped, depending on the environment. ## Usage ```rust -extern crate random_access_storage; - use random_access_storage::{RandomAccessMethods, RandomAccess}; +use async_trait::async_trait; struct S; +#[async_trait] impl RandomAccessMethods for S { type Error = std::io::Error; - fn open(&mut self) -> Result<(), Self::Error> { + async fn open(&mut self) -> Result<(), Self::Error> { unimplemented!(); } - fn write(&mut self, offset: u64, data: &[u8]) -> Result<(), Self::Error> { + async fn write(&mut self, offset: u64, data: &[u8]) -> Result<(), Self::Error> { unimplemented!(); } - fn read(&mut self, offset: u64, length: u64) -> Result, Self::Error> { + async fn read(&mut self, offset: u64, length: u64) -> Result, Self::Error> { unimplemented!(); } - fn read_to_writer( + async fn read_to_writer( &mut self, offset: u64, length: u64, - writer: &mut impl std::io::Writer + writer: &mut (impl futures::io::AsyncWriter + Send) ) -> Result<(), Self::Error> { unimplemented!(); } - fn del(&mut self, offset: u64, length: u64) -> Result<(), Self::Error> { + async fn del(&mut self, offset: u64, length: u64) -> Result<(), Self::Error> { unimplemented!(); } - fn truncate(&mut self, length: u64) -> Result<(), Self::Error> { + async fn truncate(&mut self, length: u64) -> Result<(), Self::Error> { unimplemented!(); } - fn len(&mut self) -> Result { + async fn len(&mut self) -> Result { unimplemented!(); } - fn is_empty(&mut self) -> Result { + async fn is_empty(&mut self) -> Result { unimplemented!(); } - fn sync_all(&mut self) -> Result<(), Self::Error> { + async fn sync_all(&mut self) -> Result<(), Self::Error> { unimplemented!(); } } diff --git a/src/lib.rs b/src/lib.rs index 1f9772f..ebffdf1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,43 +3,50 @@ #![cfg_attr(feature = "nightly", doc(include = "../README.md"))] #![cfg_attr(test, deny(warnings))] -use std::io; - /// The `RandomAccess` trait allows for reading from and writing to a /// randomly accessible storage of bytes. +#[async_trait::async_trait] pub trait RandomAccess { /// An error. type Error; /// Write bytes at an offset to the backend. - fn write(&mut self, offset: u64, data: &[u8]) -> Result<(), Self::Error>; + async fn write( + &mut self, + offset: u64, + data: &[u8], + ) -> Result<(), Self::Error>; /// Read a sequence of bytes at an offset from the backend. - fn read(&mut self, offset: u64, length: u64) -> Result, Self::Error>; + async fn read( + &mut self, + offset: u64, + length: u64, + ) -> Result, Self::Error>; /// Read a sequence of bytes at an offset from the backend. - fn read_to_writer( + async fn read_to_writer( &mut self, offset: u64, length: u64, - buf: &mut impl io::Write, + buf: &mut (impl futures::io::AsyncWrite + Send), ) -> Result<(), Self::Error>; /// Delete a sequence of bytes at an offset from the backend. - fn del(&mut self, offset: u64, length: u64) -> Result<(), Self::Error>; + async fn del(&mut self, offset: u64, length: u64) -> Result<(), Self::Error>; /// Resize the sequence of bytes, possibly discarding or zero-padding bytes /// from the end. - fn truncate(&mut self, length: u64) -> Result<(), Self::Error>; + async fn truncate(&mut self, length: u64) -> Result<(), Self::Error>; /// Get the size of the storage in bytes. - fn len(&self) -> Result; + async fn len(&self) -> Result; /// Whether the storage is empty. /// For some storage backends it may be cheaper to calculate whether the /// storage is empty than to calculate the length. - fn is_empty(&mut self) -> Result; + async fn is_empty(&mut self) -> Result; /// Flush buffered data on the underlying storage resource. - fn sync_all(&mut self) -> Result<(), Self::Error>; + async fn sync_all(&mut self) -> Result<(), Self::Error>; } From 2f5f4a0567db834f72afc6b75c512f309c9f4b13 Mon Sep 17 00:00:00 2001 From: Bruno Tavares Date: Mon, 2 Mar 2020 09:42:59 -0300 Subject: [PATCH 2/2] Github feedback: use futures-io to help with compile times --- Cargo.toml | 2 +- src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cb5cb0d..047d0ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,4 +11,4 @@ edition = "2018" [dependencies] async-trait = "0.1.24" -futures = "0.3.4" +futures-io = "0.3.4" diff --git a/src/lib.rs b/src/lib.rs index ebffdf1..04be02a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,7 @@ pub trait RandomAccess { &mut self, offset: u64, length: u64, - buf: &mut (impl futures::io::AsyncWrite + Send), + buf: &mut (impl futures_io::AsyncWrite + Send), ) -> Result<(), Self::Error>; /// Delete a sequence of bytes at an offset from the backend.