mirror of https://github.com/zkat/cacache-rs.git
Merge 81fe1309db into 105692a4da
This commit is contained in:
commit
f5af0ae52d
|
|
@ -28,7 +28,7 @@ jobs:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
rust: [1.70.0, stable]
|
rust: [1.81.0, stable]
|
||||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -50,3 +50,7 @@ jobs:
|
||||||
run: cargo check --no-default-features --features tokio-runtime,link_to
|
run: cargo check --no-default-features --features tokio-runtime,link_to
|
||||||
- name: Run unit tests (Tokio)
|
- name: Run unit tests (Tokio)
|
||||||
run: cargo test --verbose --no-default-features --features tokio-runtime,link_to --lib
|
run: cargo test --verbose --no-default-features --features tokio-runtime,link_to --lib
|
||||||
|
- name: Check (Smol)
|
||||||
|
run: cargo check --no-default-features --features smol-runtime,link_to
|
||||||
|
- name: Run unit tests (Smol)
|
||||||
|
run: cargo test --verbose --no-default-features --features smol-runtime,link_to --lib
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ either = "1.6.1"
|
||||||
futures = { version = "0.3.17", optional = true }
|
futures = { version = "0.3.17", optional = true }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
memmap2 = { version = "0.5.8", optional = true }
|
memmap2 = { version = "0.5.8", optional = true }
|
||||||
|
smol = { version = "2.0.0", optional = true }
|
||||||
miette = "5.7.0"
|
miette = "5.7.0"
|
||||||
reflink-copy = "0.1.9"
|
reflink-copy = "0.1.9"
|
||||||
serde = "1.0.130"
|
serde = "1.0.130"
|
||||||
|
|
@ -43,6 +44,8 @@ libc = { version = "0.2.144", optional = true }
|
||||||
async-attributes = { version = "1.1.2" }
|
async-attributes = { version = "1.1.2" }
|
||||||
criterion = "0.4.0"
|
criterion = "0.4.0"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
smol-macros = "0.1.1"
|
||||||
|
macro_rules_attribute = "0.2.0"
|
||||||
tokio = { version = "1.12.0", features = [
|
tokio = { version = "1.12.0", features = [
|
||||||
"fs",
|
"fs",
|
||||||
"io-util",
|
"io-util",
|
||||||
|
|
@ -61,3 +64,4 @@ mmap = ["memmap2", "libc"]
|
||||||
async-std = ["dep:async-std", "futures"]
|
async-std = ["dep:async-std", "futures"]
|
||||||
link_to = []
|
link_to = []
|
||||||
tokio-runtime = ["tokio", "tokio-stream", "futures"]
|
tokio-runtime = ["tokio", "tokio-stream", "futures"]
|
||||||
|
smol-runtime = ["smol", "futures"]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
use async_std::fs as afs;
|
use async_std::fs as afs;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use smol::fs as afs;
|
||||||
#[cfg(feature = "link_to")]
|
#[cfg(feature = "link_to")]
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
#[cfg(all(test, feature = "tokio"))]
|
#[cfg(all(test, feature = "tokio"))]
|
||||||
|
|
@ -22,6 +24,15 @@ where
|
||||||
TOKIO_RUNTIME.block_on(future)
|
TOKIO_RUNTIME.block_on(future)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(test, feature = "smol"))]
|
||||||
|
#[inline]
|
||||||
|
pub fn block_on<F, T>(future: F) -> T
|
||||||
|
where
|
||||||
|
F: std::future::Future<Output = T>,
|
||||||
|
{
|
||||||
|
smol::block_on(future)
|
||||||
|
}
|
||||||
|
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
|
||||||
|
|
@ -62,7 +73,7 @@ fn baseline_read_many_sync(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
fn baseline_read_async(c: &mut Criterion) {
|
fn baseline_read_async(c: &mut Criterion) {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let path = tmp.path().join("test_file");
|
let path = tmp.path().join("test_file");
|
||||||
|
|
@ -75,7 +86,7 @@ fn baseline_read_async(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
fn baseline_read_many_async(c: &mut Criterion) {
|
fn baseline_read_many_async(c: &mut Criterion) {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let paths: Vec<_> = (0..)
|
let paths: Vec<_> = (0..)
|
||||||
|
|
@ -190,7 +201,7 @@ fn read_hash_sync_big_data_xxh3(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
fn read_hash_many_async(c: &mut Criterion) {
|
fn read_hash_many_async(c: &mut Criterion) {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let cache = tmp.path().to_owned();
|
let cache = tmp.path().to_owned();
|
||||||
|
|
@ -212,7 +223,7 @@ fn read_hash_many_async(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
fn read_hash_async(c: &mut Criterion) {
|
fn read_hash_async(c: &mut Criterion) {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let cache = tmp.path().to_owned();
|
let cache = tmp.path().to_owned();
|
||||||
|
|
@ -223,7 +234,7 @@ fn read_hash_async(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
fn read_async(c: &mut Criterion) {
|
fn read_async(c: &mut Criterion) {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let cache = tmp.path().to_owned();
|
let cache = tmp.path().to_owned();
|
||||||
|
|
@ -234,7 +245,7 @@ fn read_async(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
fn read_hash_async_big_data(c: &mut Criterion) {
|
fn read_hash_async_big_data(c: &mut Criterion) {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let cache = tmp.path().to_owned();
|
let cache = tmp.path().to_owned();
|
||||||
|
|
@ -278,7 +289,7 @@ fn write_hash_xxh3(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
fn write_hash_async(c: &mut Criterion) {
|
fn write_hash_async(c: &mut Criterion) {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let cache = tmp.path().to_owned();
|
let cache = tmp.path().to_owned();
|
||||||
|
|
@ -293,7 +304,7 @@ fn write_hash_async(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
fn write_hash_async_xxh3(c: &mut Criterion) {
|
fn write_hash_async_xxh3(c: &mut Criterion) {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let cache = tmp.path().to_owned();
|
let cache = tmp.path().to_owned();
|
||||||
|
|
@ -325,7 +336,7 @@ fn create_tmpfile(tmp: &tempfile::TempDir, buf: &[u8]) -> PathBuf {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "link_to")]
|
#[cfg(feature = "link_to")]
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
fn link_to_async(c: &mut Criterion) {
|
fn link_to_async(c: &mut Criterion) {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let target = create_tmpfile(&tmp, b"hello world");
|
let target = create_tmpfile(&tmp, b"hello world");
|
||||||
|
|
@ -348,7 +359,10 @@ fn link_to_async(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "link_to", any(feature = "async-std", feature = "tokio")))]
|
#[cfg(all(
|
||||||
|
feature = "link_to",
|
||||||
|
any(feature = "async-std", feature = "tokio", feature = "smol")
|
||||||
|
))]
|
||||||
fn link_to_hash_async(c: &mut Criterion) {
|
fn link_to_hash_async(c: &mut Criterion) {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let target = create_tmpfile(&tmp, b"hello world");
|
let target = create_tmpfile(&tmp, b"hello world");
|
||||||
|
|
@ -405,7 +419,7 @@ criterion_group!(
|
||||||
read_hash_sync_big_data_xxh3,
|
read_hash_sync_big_data_xxh3,
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
criterion_group!(
|
criterion_group!(
|
||||||
benches_async,
|
benches_async,
|
||||||
baseline_read_async,
|
baseline_read_async,
|
||||||
|
|
@ -418,7 +432,10 @@ criterion_group!(
|
||||||
read_hash_async_big_data,
|
read_hash_async_big_data,
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(all(feature = "link_to", any(feature = "async-std", feature = "tokio")))]
|
#[cfg(all(
|
||||||
|
feature = "link_to",
|
||||||
|
any(feature = "async-std", feature = "tokio", feature = "smol")
|
||||||
|
))]
|
||||||
criterion_group!(link_to_benches_async, link_to_async, link_to_hash_async,);
|
criterion_group!(link_to_benches_async, link_to_async, link_to_hash_async,);
|
||||||
|
|
||||||
#[cfg(feature = "link_to")]
|
#[cfg(feature = "link_to")]
|
||||||
|
|
@ -426,15 +443,18 @@ criterion_group!(link_to_benches, link_to_sync, link_to_hash_sync);
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
feature = "link_to",
|
feature = "link_to",
|
||||||
not(any(feature = "async-std", feature = "tokio"))
|
not(any(feature = "async-std", feature = "tokio", feature = "smol"))
|
||||||
))]
|
))]
|
||||||
criterion_main!(benches, link_to_benches);
|
criterion_main!(benches, link_to_benches);
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
not(feature = "link_to"),
|
not(feature = "link_to"),
|
||||||
any(feature = "async-std", feature = "tokio")
|
any(feature = "async-std", feature = "tokio", feature = "smol")
|
||||||
))]
|
))]
|
||||||
criterion_main!(benches, benches_async);
|
criterion_main!(benches, benches_async);
|
||||||
#[cfg(all(feature = "link_to", any(feature = "async-std", feature = "tokio")))]
|
#[cfg(all(
|
||||||
|
feature = "link_to",
|
||||||
|
any(feature = "async-std", feature = "tokio", feature = "smol")
|
||||||
|
))]
|
||||||
criterion_main!(
|
criterion_main!(
|
||||||
benches,
|
benches,
|
||||||
benches_async,
|
benches_async,
|
||||||
|
|
@ -443,6 +463,6 @@ criterion_main!(
|
||||||
);
|
);
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
not(feature = "link_to"),
|
not(feature = "link_to"),
|
||||||
not(any(feature = "async-std", feature = "tokio"))
|
not(any(feature = "async-std", feature = "tokio", feature = "smol"))
|
||||||
))]
|
))]
|
||||||
criterion_main!(benches);
|
criterion_main!(benches);
|
||||||
|
|
|
||||||
8
justfile
8
justfile
|
|
@ -2,12 +2,14 @@
|
||||||
@help:
|
@help:
|
||||||
just -l
|
just -l
|
||||||
|
|
||||||
# Run tests on both runtimes with cargo nextest
|
# Run tests on all runtimes with cargo nextest
|
||||||
@test:
|
@test:
|
||||||
echo "----------\nasync-std:\n"
|
echo "----------\nasync-std:\n"
|
||||||
cargo nextest run
|
cargo nextest run
|
||||||
echo "\n----------\ntokio:\n"
|
echo "\n----------\ntokio:\n"
|
||||||
cargo nextest run --no-default-features --features tokio-runtime
|
cargo nextest run --no-default-features --features tokio-runtime
|
||||||
|
echo "\n----------\nsmol:\n"
|
||||||
|
cargo nextest run --no-default-features --features smol-runtime
|
||||||
|
|
||||||
# Run benchmarks with `cargo bench`
|
# Run benchmarks with `cargo bench`
|
||||||
@bench:
|
@bench:
|
||||||
|
|
@ -15,6 +17,8 @@
|
||||||
cargo bench
|
cargo bench
|
||||||
echo "\n----------\ntokio:\n"
|
echo "\n----------\ntokio:\n"
|
||||||
cargo bench --no-default-features --features tokio-runtime
|
cargo bench --no-default-features --features tokio-runtime
|
||||||
|
echo "\n----------\nsmol:\n"
|
||||||
|
cargo bench --no-default-features --features smol-runtime
|
||||||
|
|
||||||
# Run benchmarks with `cargo criterion`
|
# Run benchmarks with `cargo criterion`
|
||||||
@criterion:
|
@criterion:
|
||||||
|
|
@ -22,6 +26,8 @@
|
||||||
cargo criterion
|
cargo criterion
|
||||||
echo "\n----------\ntokio:\n"
|
echo "\n----------\ntokio:\n"
|
||||||
cargo criterion --no-default-features --features tokio-runtime
|
cargo criterion --no-default-features --features tokio-runtime
|
||||||
|
echo "\n----------\nsmol:\n"
|
||||||
|
cargo criterion --no-default-features --features smol-runtime
|
||||||
|
|
||||||
# Generate a changelog with git-cliff
|
# Generate a changelog with git-cliff
|
||||||
changelog TAG:
|
changelog TAG:
|
||||||
|
|
|
||||||
|
|
@ -1,75 +1,105 @@
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use async_std::fs::File;
|
pub use async_std::fs::File;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use smol::fs::File;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::fs::File;
|
pub use tokio::fs::File;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use futures::io::AsyncRead;
|
pub use futures::io::AsyncRead;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use futures::io::AsyncRead;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::io::AsyncRead;
|
pub use tokio::io::AsyncRead;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use futures::io::AsyncReadExt;
|
pub use futures::io::AsyncReadExt;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use futures::io::AsyncReadExt;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::io::AsyncReadExt;
|
pub use tokio::io::AsyncReadExt;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use futures::io::AsyncBufReadExt;
|
pub use futures::io::AsyncBufReadExt;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use futures::io::AsyncBufReadExt;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::io::AsyncBufReadExt;
|
pub use tokio::io::AsyncBufReadExt;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use futures::io::AsyncWrite;
|
pub use futures::io::AsyncWrite;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use futures::io::AsyncWrite;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::io::AsyncWrite;
|
pub use tokio::io::AsyncWrite;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use futures::io::AsyncWriteExt;
|
pub use futures::io::AsyncWriteExt;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use futures::io::AsyncWriteExt;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::io::AsyncWriteExt;
|
pub use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use async_std::fs::read;
|
pub use async_std::fs::read;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use smol::fs::read;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::fs::read;
|
pub use tokio::fs::read;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use async_std::fs::copy;
|
pub use async_std::fs::copy;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use smol::fs::copy;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::fs::copy;
|
pub use tokio::fs::copy;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use async_std::fs::metadata;
|
pub use async_std::fs::metadata;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use smol::fs::metadata;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::fs::metadata;
|
pub use tokio::fs::metadata;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use async_std::fs::remove_file;
|
pub use async_std::fs::remove_file;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use smol::fs::remove_file;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::fs::remove_file;
|
pub use tokio::fs::remove_file;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use async_std::fs::create_dir_all;
|
pub use async_std::fs::create_dir_all;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use smol::fs::create_dir_all;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::fs::create_dir_all;
|
pub use tokio::fs::create_dir_all;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use async_std::fs::remove_dir_all;
|
pub use async_std::fs::remove_dir_all;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use smol::fs::remove_dir_all;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::fs::remove_dir_all;
|
pub use tokio::fs::remove_dir_all;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use async_std::fs::DirBuilder;
|
pub use async_std::fs::DirBuilder;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use smol::fs::DirBuilder;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::fs::DirBuilder;
|
pub use tokio::fs::DirBuilder;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use async_std::fs::OpenOptions;
|
pub use async_std::fs::OpenOptions;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use smol::fs::OpenOptions;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::fs::OpenOptions;
|
pub use tokio::fs::OpenOptions;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use async_std::io::BufReader;
|
pub use async_std::io::BufReader;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use futures::io::BufReader;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::io::BufReader;
|
pub use tokio::io::BufReader;
|
||||||
|
|
||||||
|
|
@ -83,9 +113,16 @@ pub fn lines_to_stream<R>(lines: futures::io::Lines<R>) -> futures::io::Lines<R>
|
||||||
pub fn lines_to_stream<R>(lines: tokio::io::Lines<R>) -> tokio_stream::wrappers::LinesStream<R> {
|
pub fn lines_to_stream<R>(lines: tokio::io::Lines<R>) -> tokio_stream::wrappers::LinesStream<R> {
|
||||||
tokio_stream::wrappers::LinesStream::new(lines)
|
tokio_stream::wrappers::LinesStream::new(lines)
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[inline]
|
||||||
|
pub fn lines_to_stream<R>(lines: futures::io::Lines<R>) -> futures::io::Lines<R> {
|
||||||
|
lines
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
pub use async_std::task::spawn_blocking;
|
pub use async_std::task::spawn_blocking;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use smol::unblock as spawn_blocking;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
pub use tokio::task::spawn_blocking;
|
pub use tokio::task::spawn_blocking;
|
||||||
|
|
||||||
|
|
@ -103,6 +140,13 @@ pub use tokio::task::JoinHandle;
|
||||||
pub fn unwrap_joinhandle_value<T>(value: T) -> T {
|
pub fn unwrap_joinhandle_value<T>(value: T) -> T {
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
pub use smol::Task as JoinHandle;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[inline]
|
||||||
|
pub fn unwrap_joinhandle_value<T>(value: T) -> T {
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
|
|
@ -135,3 +179,17 @@ pub async fn create_named_tempfile(
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[inline]
|
||||||
|
pub async fn create_named_tempfile(
|
||||||
|
tmp_path: std::path::PathBuf,
|
||||||
|
) -> Option<crate::Result<NamedTempFile>> {
|
||||||
|
let cloned = tmp_path.clone();
|
||||||
|
|
||||||
|
Some(
|
||||||
|
spawn_blocking(|| NamedTempFile::new_in(tmp_path))
|
||||||
|
.await
|
||||||
|
.with_context(|| format!("Failed to create a temp file at {}", cloned.display())),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@ use ssri::{Algorithm, Integrity, IntegrityOpts};
|
||||||
use std::fs::DirBuilder;
|
use std::fs::DirBuilder;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use crate::async_lib::AsyncRead;
|
use crate::async_lib::AsyncRead;
|
||||||
use crate::content::path;
|
use crate::content::path;
|
||||||
use crate::errors::{IoErrorExt, Result};
|
use crate::errors::{IoErrorExt, Result};
|
||||||
|
|
@ -106,7 +106,7 @@ impl std::io::Read for ToLinker {
|
||||||
/// An `AsyncRead`-like type that calculates the integrity of a file as it is
|
/// An `AsyncRead`-like type that calculates the integrity of a file as it is
|
||||||
/// read. When the linker is committed, a symlink is created from the cache to
|
/// read. When the linker is committed, a symlink is created from the cache to
|
||||||
/// the target file using the integrity computed from the file's contents.
|
/// the target file using the integrity computed from the file's contents.
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub struct AsyncToLinker {
|
pub struct AsyncToLinker {
|
||||||
/// The path to the target file that will be symlinked from the cache.
|
/// The path to the target file that will be symlinked from the cache.
|
||||||
target: PathBuf,
|
target: PathBuf,
|
||||||
|
|
@ -118,7 +118,7 @@ pub struct AsyncToLinker {
|
||||||
builder: IntegrityOpts,
|
builder: IntegrityOpts,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
impl AsyncRead for AsyncToLinker {
|
impl AsyncRead for AsyncToLinker {
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
fn poll_read(
|
fn poll_read(
|
||||||
|
|
@ -146,9 +146,22 @@ impl AsyncRead for AsyncToLinker {
|
||||||
}
|
}
|
||||||
Poll::Ready(Ok(()))
|
Poll::Ready(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
fn poll_read(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Poll<std::io::Result<usize>> {
|
||||||
|
let amt = futures::ready!(Pin::new(&mut self.fd).poll_read(cx, buf))?;
|
||||||
|
if amt > 0 {
|
||||||
|
self.builder.input(&buf[..amt]);
|
||||||
|
}
|
||||||
|
Poll::Ready(Ok(amt))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
impl AsyncToLinker {
|
impl AsyncToLinker {
|
||||||
pub async fn new(cache: &Path, algo: Algorithm, target: &Path) -> Result<Self> {
|
pub async fn new(cache: &Path, algo: Algorithm, target: &Path) -> Result<Self> {
|
||||||
let file = crate::async_lib::File::open(target)
|
let file = crate::async_lib::File::open(target)
|
||||||
|
|
@ -176,11 +189,17 @@ mod tests {
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
use async_attributes::test as async_test;
|
use async_attributes::test as async_test;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use macro_rules_attribute::apply;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use smol_macros::test;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
use tokio::test as async_test;
|
use tokio::test as async_test;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
use futures::io::AsyncReadExt;
|
use futures::io::AsyncReadExt;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use futures::io::AsyncReadExt;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
|
|
||||||
|
|
@ -254,4 +273,37 @@ mod tests {
|
||||||
assert!(file_type.is_symlink());
|
assert!(file_type.is_symlink());
|
||||||
assert_eq!(std::fs::read(cpath).unwrap(), b"hello world");
|
assert_eq!(std::fs::read(cpath).unwrap(), b"hello world");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn basic_async_link() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let target = create_tmpfile(&tmp, b"hello world");
|
||||||
|
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let mut linker = AsyncToLinker::new(&dir, Algorithm::Sha256, &target)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// read all of the data from the linker, which will calculate the integrity
|
||||||
|
// hash.
|
||||||
|
let mut buf: Vec<u8> = Vec::new();
|
||||||
|
AsyncReadExt::read_to_end(&mut linker, &mut buf)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(buf, b"hello world");
|
||||||
|
|
||||||
|
// commit the linker, creating a symlink in the cache and an integrity
|
||||||
|
// hash.
|
||||||
|
let sri = linker.commit().await.unwrap();
|
||||||
|
assert_eq!(sri.to_string(), Integrity::from(b"hello world").to_string());
|
||||||
|
|
||||||
|
let cpath = path::content_path(&dir, &sri);
|
||||||
|
assert!(cpath.exists());
|
||||||
|
let metadata = std::fs::symlink_metadata(&cpath).unwrap();
|
||||||
|
let file_type = metadata.file_type();
|
||||||
|
assert!(file_type.is_symlink());
|
||||||
|
assert_eq!(std::fs::read(cpath).unwrap(), b"hello world");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use crate::async_lib::AsyncReadExt;
|
use crate::async_lib::AsyncReadExt;
|
||||||
|
|
||||||
use ssri::{Algorithm, Integrity, IntegrityChecker};
|
use ssri::{Algorithm, Integrity, IntegrityChecker};
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use crate::async_lib::AsyncRead;
|
use crate::async_lib::AsyncRead;
|
||||||
use crate::content::path;
|
use crate::content::path;
|
||||||
use crate::errors::{IoErrorExt, Result};
|
use crate::errors::{IoErrorExt, Result};
|
||||||
|
|
@ -35,13 +35,13 @@ impl Reader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub struct AsyncReader {
|
pub struct AsyncReader {
|
||||||
fd: crate::async_lib::File,
|
fd: crate::async_lib::File,
|
||||||
checker: IntegrityChecker,
|
checker: IntegrityChecker,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
impl AsyncRead for AsyncReader {
|
impl AsyncRead for AsyncReader {
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
fn poll_read(
|
fn poll_read(
|
||||||
|
|
@ -69,9 +69,20 @@ impl AsyncRead for AsyncReader {
|
||||||
self.checker.input(&buf.filled()[pre_len..]);
|
self.checker.input(&buf.filled()[pre_len..]);
|
||||||
Poll::Ready(Ok(()))
|
Poll::Ready(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
fn poll_read(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Poll<std::io::Result<usize>> {
|
||||||
|
let amt = futures::ready!(Pin::new(&mut self.fd).poll_read(cx, buf))?;
|
||||||
|
self.checker.input(&buf[..amt]);
|
||||||
|
Poll::Ready(Ok(amt))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
impl AsyncReader {
|
impl AsyncReader {
|
||||||
pub fn check(self) -> Result<Algorithm> {
|
pub fn check(self) -> Result<Algorithm> {
|
||||||
Ok(self.checker.result()?)
|
Ok(self.checker.result()?)
|
||||||
|
|
@ -91,7 +102,7 @@ pub fn open(cache: &Path, sri: Integrity) -> Result<Reader> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn open_async(cache: &Path, sri: Integrity) -> Result<AsyncReader> {
|
pub async fn open_async(cache: &Path, sri: Integrity) -> Result<AsyncReader> {
|
||||||
let cpath = path::content_path(cache, &sri);
|
let cpath = path::content_path(cache, &sri);
|
||||||
Ok(AsyncReader {
|
Ok(AsyncReader {
|
||||||
|
|
@ -117,7 +128,7 @@ pub fn read(cache: &Path, sri: &Integrity) -> Result<Vec<u8>> {
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn read_async<'a>(cache: &'a Path, sri: &'a Integrity) -> Result<Vec<u8>> {
|
pub async fn read_async<'a>(cache: &'a Path, sri: &'a Integrity) -> Result<Vec<u8>> {
|
||||||
let cpath = path::content_path(cache, sri);
|
let cpath = path::content_path(cache, sri);
|
||||||
let ret = crate::async_lib::read(&cpath).await.with_context(|| {
|
let ret = crate::async_lib::read(&cpath).await.with_context(|| {
|
||||||
|
|
@ -160,7 +171,7 @@ pub fn reflink(cache: &Path, sri: &Integrity, to: &Path) -> Result<()> {
|
||||||
reflink_unchecked(cache, sri, to)
|
reflink_unchecked(cache, sri, to)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn reflink_async(cache: &Path, sri: &Integrity, to: &Path) -> Result<()> {
|
pub async fn reflink_async(cache: &Path, sri: &Integrity, to: &Path) -> Result<()> {
|
||||||
let mut reader = open_async(cache, sri.clone()).await?;
|
let mut reader = open_async(cache, sri.clone()).await?;
|
||||||
let mut buf = [0u8; 1024 * 8];
|
let mut buf = [0u8; 1024 * 8];
|
||||||
|
|
@ -214,7 +225,7 @@ pub fn copy(cache: &Path, sri: &Integrity, to: &Path) -> Result<u64> {
|
||||||
Ok(size as u64)
|
Ok(size as u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn copy_unchecked_async<'a>(
|
pub async fn copy_unchecked_async<'a>(
|
||||||
cache: &'a Path,
|
cache: &'a Path,
|
||||||
sri: &'a Integrity,
|
sri: &'a Integrity,
|
||||||
|
|
@ -230,7 +241,7 @@ pub async fn copy_unchecked_async<'a>(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn copy_async<'a>(cache: &'a Path, sri: &'a Integrity, to: &'a Path) -> Result<u64> {
|
pub async fn copy_async<'a>(cache: &'a Path, sri: &'a Integrity, to: &'a Path) -> Result<u64> {
|
||||||
let mut reader = open_async(cache, sri.clone()).await?;
|
let mut reader = open_async(cache, sri.clone()).await?;
|
||||||
let mut buf: [u8; 1024] = [0; 1024];
|
let mut buf: [u8; 1024] = [0; 1024];
|
||||||
|
|
@ -285,7 +296,7 @@ pub fn hard_link(cache: &Path, sri: &Integrity, to: &Path) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn hard_link_async(cache: &Path, sri: &Integrity, to: &Path) -> Result<()> {
|
pub async fn hard_link_async(cache: &Path, sri: &Integrity, to: &Path) -> Result<()> {
|
||||||
let mut reader = open_async(cache, sri.clone()).await?;
|
let mut reader = open_async(cache, sri.clone()).await?;
|
||||||
let mut buf = [0u8; 1024 * 8];
|
let mut buf = [0u8; 1024 * 8];
|
||||||
|
|
@ -315,7 +326,7 @@ pub fn has_content(cache: &Path, sri: &Integrity) -> Option<Integrity> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn has_content_async(cache: &Path, sri: &Integrity) -> Option<Integrity> {
|
pub async fn has_content_async(cache: &Path, sri: &Integrity) -> Option<Integrity> {
|
||||||
if crate::async_lib::metadata(path::content_path(cache, sri))
|
if crate::async_lib::metadata(path::content_path(cache, sri))
|
||||||
.await
|
.await
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ pub fn rm(cache: &Path, sri: &Integrity) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn rm_async(cache: &Path, sri: &Integrity) -> Result<()> {
|
pub async fn rm_async(cache: &Path, sri: &Integrity) -> Result<()> {
|
||||||
crate::async_lib::remove_file(path::content_path(cache, sri))
|
crate::async_lib::remove_file(path::content_path(cache, sri))
|
||||||
.await
|
.await
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
use std::fs::DirBuilder;
|
use std::fs::DirBuilder;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
#[cfg(feature = "mmap")]
|
#[cfg(feature = "mmap")]
|
||||||
use memmap2::MmapMut;
|
use memmap2::MmapMut;
|
||||||
use ssri::{Algorithm, Integrity, IntegrityOpts};
|
use ssri::{Algorithm, Integrity, IntegrityOpts};
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use crate::async_lib::{AsyncWrite, JoinHandle};
|
use crate::async_lib::{AsyncWrite, JoinHandle};
|
||||||
use crate::content::path;
|
use crate::content::path;
|
||||||
use crate::errors::{IoErrorExt, Result};
|
use crate::errors::{IoErrorExt, Result};
|
||||||
|
|
@ -129,16 +129,16 @@ impl Write for Writer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub struct AsyncWriter(Mutex<State>);
|
pub struct AsyncWriter(Mutex<State>);
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
enum State {
|
enum State {
|
||||||
Idle(Option<Inner>),
|
Idle(Option<Inner>),
|
||||||
Busy(JoinHandle<State>),
|
Busy(JoinHandle<State>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
struct Inner {
|
struct Inner {
|
||||||
cache: PathBuf,
|
cache: PathBuf,
|
||||||
builder: IntegrityOpts,
|
builder: IntegrityOpts,
|
||||||
|
|
@ -148,13 +148,13 @@ struct Inner {
|
||||||
last_op: Option<Operation>,
|
last_op: Option<Operation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
enum Operation {
|
enum Operation {
|
||||||
Write(std::io::Result<usize>),
|
Write(std::io::Result<usize>),
|
||||||
Flush(std::io::Result<()>),
|
Flush(std::io::Result<()>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
impl AsyncWriter {
|
impl AsyncWriter {
|
||||||
#[allow(clippy::new_ret_no_self)]
|
#[allow(clippy::new_ret_no_self)]
|
||||||
#[allow(clippy::needless_lifetimes)]
|
#[allow(clippy::needless_lifetimes)]
|
||||||
|
|
@ -187,7 +187,7 @@ impl AsyncWriter {
|
||||||
})))))
|
})))))
|
||||||
}
|
}
|
||||||
_ => Err(Error::IoError(
|
_ => Err(Error::IoError(
|
||||||
std::io::Error::new(std::io::ErrorKind::Other, "temp file create error"),
|
std::io::Error::other("temp file create error"),
|
||||||
"Possible memory issues for file handle".into(),
|
"Possible memory issues for file handle".into(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
|
|
@ -275,7 +275,7 @@ impl AsyncWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
impl AsyncWrite for AsyncWriter {
|
impl AsyncWrite for AsyncWriter {
|
||||||
fn poll_write(
|
fn poll_write(
|
||||||
self: Pin<&mut Self>,
|
self: Pin<&mut Self>,
|
||||||
|
|
@ -407,6 +407,11 @@ impl AsyncWrite for AsyncWriter {
|
||||||
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
||||||
self.poll_close_impl(cx)
|
self.poll_close_impl(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
||||||
|
self.poll_close_impl(cx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
|
|
@ -431,7 +436,7 @@ fn update_state(current_state: &mut State, next_state: State) {
|
||||||
*current_state = next_state;
|
*current_state = next_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
impl AsyncWriter {
|
impl AsyncWriter {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn poll_close_impl(
|
fn poll_close_impl(
|
||||||
|
|
@ -491,20 +496,18 @@ fn make_mmap(tmpfile: &mut NamedTempFile, size: Option<usize>) -> Result<Option<
|
||||||
#[cfg(feature = "mmap")]
|
#[cfg(feature = "mmap")]
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
fn allocate_file(file: &std::fs::File, size: usize) -> std::io::Result<()> {
|
fn allocate_file(file: &std::fs::File, size: usize) -> std::io::Result<()> {
|
||||||
use std::io::{Error, ErrorKind};
|
use std::io::Error;
|
||||||
use std::os::fd::AsRawFd;
|
use std::os::fd::AsRawFd;
|
||||||
|
|
||||||
let fd = file.as_raw_fd();
|
let fd = file.as_raw_fd();
|
||||||
match unsafe { libc::posix_fallocate64(fd, 0, size as i64) } {
|
match unsafe { libc::posix_fallocate64(fd, 0, size as i64) } {
|
||||||
0 => Ok(()),
|
0 => Ok(()),
|
||||||
libc::ENOSPC => Err(Error::new(
|
libc::ENOSPC => Err(Error::other(
|
||||||
ErrorKind::Other, // ErrorKind::StorageFull is unstable
|
|
||||||
"cannot allocate file: no space left on device",
|
"cannot allocate file: no space left on device",
|
||||||
)),
|
)),
|
||||||
err => Err(Error::new(
|
err => Err(Error::other(format!(
|
||||||
ErrorKind::Other,
|
"posix_fallocate64 failed with code {err}"
|
||||||
format!("posix_fallocate64 failed with code {err}"),
|
))),
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -522,12 +525,16 @@ fn make_mmap(_: &mut NamedTempFile, _: Option<usize>) -> Result<Option<MmapMut>>
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use crate::async_lib::AsyncWriteExt;
|
use crate::async_lib::AsyncWriteExt;
|
||||||
use tempfile;
|
use tempfile;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
use async_attributes::test as async_test;
|
use async_attributes::test as async_test;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use macro_rules_attribute::apply;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use smol_macros::test;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
use tokio::test as async_test;
|
use tokio::test as async_test;
|
||||||
|
|
||||||
|
|
@ -561,4 +568,21 @@ mod tests {
|
||||||
b"hello world"
|
b"hello world"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn basic_async_write() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let mut writer = AsyncWriter::new(&dir, Algorithm::Sha256, None)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
writer.write_all(b"hello world").await.unwrap();
|
||||||
|
let sri = writer.close().await.unwrap();
|
||||||
|
assert_eq!(sri.to_string(), Integrity::from(b"hello world").to_string());
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read(path::content_path(&dir, &sri)).unwrap(),
|
||||||
|
b"hello world"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,5 +59,5 @@ impl<T> IoErrorExt<T> for std::result::Result<T, serde_json::Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn io_error(err: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> std::io::Error {
|
pub fn io_error(err: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> std::io::Error {
|
||||||
std::io::Error::new(std::io::ErrorKind::Other, err)
|
std::io::Error::other(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
129
src/get.rs
129
src/get.rs
|
|
@ -1,13 +1,13 @@
|
||||||
//! Functions for reading from cache.
|
//! Functions for reading from cache.
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use std::task::{Context as TaskContext, Poll};
|
use std::task::{Context as TaskContext, Poll};
|
||||||
|
|
||||||
use ssri::{Algorithm, Integrity};
|
use ssri::{Algorithm, Integrity};
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use crate::async_lib::AsyncRead;
|
use crate::async_lib::AsyncRead;
|
||||||
use crate::content::read;
|
use crate::content::read;
|
||||||
use crate::errors::{Error, Result};
|
use crate::errors::{Error, Result};
|
||||||
|
|
@ -21,12 +21,12 @@ use crate::index::{self, Metadata};
|
||||||
///
|
///
|
||||||
/// Make sure to call `.check()` when done reading to verify that the
|
/// Make sure to call `.check()` when done reading to verify that the
|
||||||
/// extracted data passes integrity verification.
|
/// extracted data passes integrity verification.
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub struct Reader {
|
pub struct Reader {
|
||||||
reader: read::AsyncReader,
|
reader: read::AsyncReader,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
impl AsyncRead for Reader {
|
impl AsyncRead for Reader {
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
fn poll_read(
|
fn poll_read(
|
||||||
|
|
@ -45,9 +45,18 @@ impl AsyncRead for Reader {
|
||||||
) -> Poll<tokio::io::Result<()>> {
|
) -> Poll<tokio::io::Result<()>> {
|
||||||
Pin::new(&mut self.reader).poll_read(cx, buf)
|
Pin::new(&mut self.reader).poll_read(cx, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
fn poll_read(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut TaskContext<'_>,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Poll<std::io::Result<usize>> {
|
||||||
|
Pin::new(&mut self.reader).poll_read(cx, buf)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
impl Reader {
|
impl Reader {
|
||||||
/// Checks that data read from disk passes integrity checks. Returns the
|
/// Checks that data read from disk passes integrity checks. Returns the
|
||||||
/// algorithm that was used verified the data. Should be called only after
|
/// algorithm that was used verified the data. Should be called only after
|
||||||
|
|
@ -151,7 +160,7 @@ impl Reader {
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn read<P, K>(cache: P, key: K) -> Result<Vec<u8>>
|
pub async fn read<P, K>(cache: P, key: K) -> Result<Vec<u8>>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -182,7 +191,7 @@ where
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn read_hash<P>(cache: P, sri: &Integrity) -> Result<Vec<u8>>
|
pub async fn read_hash<P>(cache: P, sri: &Integrity) -> Result<Vec<u8>>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -204,7 +213,7 @@ where
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn copy<P, K, Q>(cache: P, key: K, to: Q) -> Result<u64>
|
pub async fn copy<P, K, Q>(cache: P, key: K, to: Q) -> Result<u64>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -235,7 +244,7 @@ where
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn copy_unchecked<P, K, Q>(cache: P, key: K, to: Q) -> Result<u64>
|
pub async fn copy_unchecked<P, K, Q>(cache: P, key: K, to: Q) -> Result<u64>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -267,7 +276,7 @@ where
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn copy_hash<P, Q>(cache: P, sri: &Integrity, to: Q) -> Result<u64>
|
pub async fn copy_hash<P, Q>(cache: P, sri: &Integrity, to: Q) -> Result<u64>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -291,7 +300,7 @@ where
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn copy_hash_unchecked<P, Q>(cache: P, sri: &Integrity, to: Q) -> Result<u64>
|
pub async fn copy_hash_unchecked<P, Q>(cache: P, sri: &Integrity, to: Q) -> Result<u64>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -319,7 +328,7 @@ where
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn reflink<P, K, Q>(cache: P, key: K, to: Q) -> Result<()>
|
pub async fn reflink<P, K, Q>(cache: P, key: K, to: Q) -> Result<()>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -356,7 +365,7 @@ where
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn reflink_unchecked<P, K, Q>(cache: P, key: K, to: Q) -> Result<()>
|
pub async fn reflink_unchecked<P, K, Q>(cache: P, key: K, to: Q) -> Result<()>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -393,7 +402,7 @@ where
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn reflink_hash<P, Q>(cache: P, sri: &Integrity, to: Q) -> Result<()>
|
pub async fn reflink_hash<P, Q>(cache: P, sri: &Integrity, to: Q) -> Result<()>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -403,7 +412,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hard links a cache entry by hash to a specified location.
|
/// Hard links a cache entry by hash to a specified location.
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn hard_link_hash<P, Q>(cache: P, sri: &Integrity, to: Q) -> Result<()>
|
pub async fn hard_link_hash<P, Q>(cache: P, sri: &Integrity, to: Q) -> Result<()>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -413,7 +422,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hard links a cache entry by key to a specified location.
|
/// Hard links a cache entry by key to a specified location.
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn hard_link<P, K, Q>(cache: P, key: K, to: Q) -> Result<()>
|
pub async fn hard_link<P, K, Q>(cache: P, key: K, to: Q) -> Result<()>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -435,7 +444,7 @@ where
|
||||||
/// Note that the existence of a metadata entry is not a guarantee that the
|
/// Note that the existence of a metadata entry is not a guarantee that the
|
||||||
/// underlying data exists, since they are stored and managed independently.
|
/// underlying data exists, since they are stored and managed independently.
|
||||||
/// To verify that the underlying associated data exists, use `exists()`.
|
/// To verify that the underlying associated data exists, use `exists()`.
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn metadata<P, K>(cache: P, key: K) -> Result<Option<Metadata>>
|
pub async fn metadata<P, K>(cache: P, key: K) -> Result<Option<Metadata>>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -445,7 +454,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the given hash exists in the cache.
|
/// Returns true if the given hash exists in the cache.
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn exists<P: AsRef<Path>>(cache: P, sri: &Integrity) -> bool {
|
pub async fn exists<P: AsRef<Path>>(cache: P, sri: &Integrity) -> bool {
|
||||||
read::has_content_async(cache.as_ref(), sri).await.is_some()
|
read::has_content_async(cache.as_ref(), sri).await.is_some()
|
||||||
}
|
}
|
||||||
|
|
@ -912,12 +921,16 @@ pub fn exists_sync<P: AsRef<Path>>(cache: P, sri: &Integrity) -> bool {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use crate::async_lib::AsyncReadExt;
|
use crate::async_lib::AsyncReadExt;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
use async_attributes::test as async_test;
|
use async_attributes::test as async_test;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use macro_rules_attribute::apply;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use smol_macros::test;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
use tokio::test as async_test;
|
use tokio::test as async_test;
|
||||||
|
|
||||||
|
|
@ -935,6 +948,20 @@ mod tests {
|
||||||
assert_eq!(str, String::from("hello world"));
|
assert_eq!(str, String::from("hello world"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn test_open() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
crate::write(&dir, "my-key", b"hello world").await.unwrap();
|
||||||
|
|
||||||
|
let mut handle = crate::Reader::open(&dir, "my-key").await.unwrap();
|
||||||
|
let mut str = String::new();
|
||||||
|
handle.read_to_string(&mut str).await.unwrap();
|
||||||
|
handle.check().unwrap();
|
||||||
|
assert_eq!(str, String::from("hello world"));
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
||||||
#[async_test]
|
#[async_test]
|
||||||
async fn test_open_hash() {
|
async fn test_open_hash() {
|
||||||
|
|
@ -949,6 +976,20 @@ mod tests {
|
||||||
assert_eq!(str, String::from("hello world"));
|
assert_eq!(str, String::from("hello world"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn test_open_hash() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let sri = crate::write(&dir, "my-key", b"hello world").await.unwrap();
|
||||||
|
|
||||||
|
let mut handle = crate::Reader::open_hash(&dir, sri).await.unwrap();
|
||||||
|
let mut str = String::new();
|
||||||
|
handle.read_to_string(&mut str).await.unwrap();
|
||||||
|
handle.check().unwrap();
|
||||||
|
assert_eq!(str, String::from("hello world"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_open_sync() {
|
fn test_open_sync() {
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
|
@ -988,6 +1029,17 @@ mod tests {
|
||||||
assert_eq!(data, b"hello world");
|
assert_eq!(data, b"hello world");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn test_read() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
crate::write(&dir, "my-key", b"hello world").await.unwrap();
|
||||||
|
|
||||||
|
let data = crate::read(&dir, "my-key").await.unwrap();
|
||||||
|
assert_eq!(data, b"hello world");
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
||||||
#[async_test]
|
#[async_test]
|
||||||
async fn test_read_hash() {
|
async fn test_read_hash() {
|
||||||
|
|
@ -999,6 +1051,17 @@ mod tests {
|
||||||
assert_eq!(data, b"hello world");
|
assert_eq!(data, b"hello world");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn test_read_hash() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let sri = crate::write(&dir, "my-key", b"hello world").await.unwrap();
|
||||||
|
|
||||||
|
let data = crate::read_hash(&dir, &sri).await.unwrap();
|
||||||
|
assert_eq!(data, b"hello world");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_read_sync() {
|
fn test_read_sync() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
|
@ -1032,6 +1095,19 @@ mod tests {
|
||||||
assert_eq!(data, b"hello world");
|
assert_eq!(data, b"hello world");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn test_copy() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path();
|
||||||
|
let dest = dir.join("data");
|
||||||
|
crate::write(&dir, "my-key", b"hello world").await.unwrap();
|
||||||
|
|
||||||
|
crate::copy(&dir, "my-key", &dest).await.unwrap();
|
||||||
|
let data = crate::async_lib::read(&dest).await.unwrap();
|
||||||
|
assert_eq!(data, b"hello world");
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
||||||
#[async_test]
|
#[async_test]
|
||||||
async fn test_copy_hash() {
|
async fn test_copy_hash() {
|
||||||
|
|
@ -1045,6 +1121,19 @@ mod tests {
|
||||||
assert_eq!(data, b"hello world");
|
assert_eq!(data, b"hello world");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn test_copy_hash() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path();
|
||||||
|
let dest = dir.join("data");
|
||||||
|
let sri = crate::write(&dir, "my-key", b"hello world").await.unwrap();
|
||||||
|
|
||||||
|
crate::copy_hash(&dir, &sri, &dest).await.unwrap();
|
||||||
|
let data = crate::async_lib::read(&dest).await.unwrap();
|
||||||
|
assert_eq!(data, b"hello world");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_copy_sync() {
|
fn test_copy_sync() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
|
|
||||||
95
src/index.rs
95
src/index.rs
|
|
@ -9,7 +9,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
use digest::Digest;
|
use digest::Digest;
|
||||||
use either::{Left, Right};
|
use either::{Left, Right};
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
@ -18,7 +18,7 @@ use sha2::Sha256;
|
||||||
use ssri::Integrity;
|
use ssri::Integrity;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use crate::async_lib::{AsyncBufReadExt, AsyncWriteExt};
|
use crate::async_lib::{AsyncBufReadExt, AsyncWriteExt};
|
||||||
use crate::content::path::content_path;
|
use crate::content::path::content_path;
|
||||||
use crate::errors::{IoErrorExt, Result};
|
use crate::errors::{IoErrorExt, Result};
|
||||||
|
|
@ -103,7 +103,7 @@ pub fn insert(cache: &Path, key: &str, opts: WriteOpts) -> Result<Integrity> {
|
||||||
.unwrap())
|
.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
/// Asynchronous raw insertion into the cache index.
|
/// Asynchronous raw insertion into the cache index.
|
||||||
pub async fn insert_async<'a>(cache: &'a Path, key: &'a str, opts: WriteOpts) -> Result<Integrity> {
|
pub async fn insert_async<'a>(cache: &'a Path, key: &'a str, opts: WriteOpts) -> Result<Integrity> {
|
||||||
let bucket = bucket_path(cache, key);
|
let bucket = bucket_path(cache, key);
|
||||||
|
|
@ -175,7 +175,7 @@ pub fn find(cache: &Path, key: &str) -> Result<Option<Metadata>> {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
/// Asynchronous raw index Metadata access.
|
/// Asynchronous raw index Metadata access.
|
||||||
pub async fn find_async(cache: &Path, key: &str) -> Result<Option<Metadata>> {
|
pub async fn find_async(cache: &Path, key: &str) -> Result<Option<Metadata>> {
|
||||||
let bucket = bucket_path(cache, key);
|
let bucket = bucket_path(cache, key);
|
||||||
|
|
@ -224,7 +224,7 @@ pub fn delete(cache: &Path, key: &str) -> Result<()> {
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
/// Asynchronously deletes an index entry, without deleting the actual cache
|
/// Asynchronously deletes an index entry, without deleting the actual cache
|
||||||
/// data entry.
|
/// data entry.
|
||||||
pub async fn delete_async(cache: &Path, key: &str) -> Result<()> {
|
pub async fn delete_async(cache: &Path, key: &str) -> Result<()> {
|
||||||
|
|
@ -351,7 +351,7 @@ fn bucket_entries(bucket: &Path) -> std::io::Result<Vec<SerializableMetadata>> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
async fn bucket_entries_async(bucket: &Path) -> std::io::Result<Vec<SerializableMetadata>> {
|
async fn bucket_entries_async(bucket: &Path) -> std::io::Result<Vec<SerializableMetadata>> {
|
||||||
let file_result = crate::async_lib::File::open(bucket).await;
|
let file_result = crate::async_lib::File::open(bucket).await;
|
||||||
let file = if let Err(err) = file_result {
|
let file = if let Err(err) = file_result {
|
||||||
|
|
@ -424,7 +424,7 @@ impl RemoveOpts {
|
||||||
/// Removes an individual index metadata entry.
|
/// Removes an individual index metadata entry.
|
||||||
/// If remove_fully is set to false (default), the associated content will be left in the cache.
|
/// If remove_fully is set to false (default), the associated content will be left in the cache.
|
||||||
/// If remove_fully is true, both the index entry and the contents will be physically removed from the disk
|
/// If remove_fully is true, both the index entry and the contents will be physically removed from the disk
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn remove<P, K>(self, cache: P, key: K) -> Result<()>
|
pub async fn remove<P, K>(self, cache: P, key: K) -> Result<()>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -454,6 +454,10 @@ mod tests {
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
use async_attributes::test as async_test;
|
use async_attributes::test as async_test;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use macro_rules_attribute::apply;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use smol_macros::test;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
use tokio::test as async_test;
|
use tokio::test as async_test;
|
||||||
|
|
||||||
|
|
@ -495,6 +499,21 @@ mod tests {
|
||||||
assert_eq!(entry, MOCK_ENTRY);
|
assert_eq!(entry, MOCK_ENTRY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn insert_async_basic() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let sri: Integrity = "sha1-deadbeef".parse().unwrap();
|
||||||
|
let time = 1_234_567;
|
||||||
|
let opts = WriteOpts::new().integrity(sri).time(time);
|
||||||
|
futures::executor::block_on(async {
|
||||||
|
insert_async(&dir, "hello", opts).await.unwrap();
|
||||||
|
});
|
||||||
|
let entry = std::fs::read_to_string(bucket_path(&dir, "hello")).unwrap();
|
||||||
|
assert_eq!(entry, MOCK_ENTRY);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn find_basic() {
|
fn find_basic() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
|
@ -552,6 +571,21 @@ mod tests {
|
||||||
assert_eq!(find(&dir, "hello").unwrap(), None);
|
assert_eq!(find(&dir, "hello").unwrap(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn delete_async_basic() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let sri: Integrity = "sha1-deadbeef".parse().unwrap();
|
||||||
|
let time = 1_234_567;
|
||||||
|
let opts = WriteOpts::new().integrity(sri).time(time);
|
||||||
|
insert(&dir, "hello", opts).unwrap();
|
||||||
|
futures::executor::block_on(async {
|
||||||
|
delete_async(&dir, "hello").await.unwrap();
|
||||||
|
});
|
||||||
|
assert_eq!(find(&dir, "hello").unwrap(), None);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn delete_fully() {
|
fn delete_fully() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
|
@ -590,6 +624,26 @@ mod tests {
|
||||||
assert!(!content.exists());
|
assert!(!content.exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn delete_fully_async() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let content = content_path(&dir, &"sha1-deadbeef".parse().unwrap());
|
||||||
|
fs::create_dir_all(content.parent().unwrap()).unwrap();
|
||||||
|
fs::write(content.as_path(), "hello").unwrap();
|
||||||
|
let sri: Integrity = "sha1-deadbeef".parse().unwrap();
|
||||||
|
let time = 1_234_567;
|
||||||
|
insert(&dir, "hello", WriteOpts::new().integrity(sri).time(time)).unwrap();
|
||||||
|
RemoveOpts::new()
|
||||||
|
.remove_fully(true)
|
||||||
|
.remove(&dir, "hello")
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(find(&dir, "hello").unwrap(), None);
|
||||||
|
assert!(!content.exists());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn round_trip() {
|
fn round_trip() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
|
@ -639,6 +693,33 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn round_trip_async() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let sri: Integrity = "sha1-deadbeef".parse().unwrap();
|
||||||
|
let time = 1_234_567;
|
||||||
|
let opts = WriteOpts::new().integrity(sri.clone()).time(time);
|
||||||
|
futures::executor::block_on(async {
|
||||||
|
insert_async(&dir, "hello", opts).await.unwrap();
|
||||||
|
});
|
||||||
|
let entry = futures::executor::block_on(async {
|
||||||
|
find_async(&dir, "hello").await.unwrap().unwrap()
|
||||||
|
});
|
||||||
|
assert_eq!(
|
||||||
|
entry,
|
||||||
|
Metadata {
|
||||||
|
key: String::from("hello"),
|
||||||
|
integrity: sri,
|
||||||
|
time,
|
||||||
|
size: 0,
|
||||||
|
metadata: json!(null),
|
||||||
|
raw_metadata: None,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ls_basic() {
|
fn ls_basic() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
|
|
||||||
12
src/lib.rs
12
src/lib.rs
|
|
@ -156,10 +156,20 @@
|
||||||
#[cfg(all(feature = "async-std", feature = "tokio-runtime"))]
|
#[cfg(all(feature = "async-std", feature = "tokio-runtime"))]
|
||||||
compile_error!("Only either feature \"async-std\" or \"tokio-runtime\" must be enabled for this crate, not both.");
|
compile_error!("Only either feature \"async-std\" or \"tokio-runtime\" must be enabled for this crate, not both.");
|
||||||
|
|
||||||
|
#[cfg(all(feature = "async-std", feature = "smol"))]
|
||||||
|
compile_error!(
|
||||||
|
"Only either feature \"async-std\" or \"smol\" must be enabled for this crate, not both."
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(all(feature = "tokio-runtime", feature = "smol"))]
|
||||||
|
compile_error!(
|
||||||
|
"Only either feature \"tokio-runtime\" or \"smol\" must be enabled for this crate, not both."
|
||||||
|
);
|
||||||
|
|
||||||
pub use serde_json::Value;
|
pub use serde_json::Value;
|
||||||
pub use ssri::{Algorithm, Integrity};
|
pub use ssri::{Algorithm, Integrity};
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
mod async_lib;
|
mod async_lib;
|
||||||
|
|
||||||
mod content;
|
mod content;
|
||||||
|
|
|
||||||
103
src/linkto.rs
103
src/linkto.rs
|
|
@ -1,6 +1,6 @@
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use crate::async_lib::AsyncRead;
|
use crate::async_lib::AsyncRead;
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use crate::async_lib::AsyncReadExt;
|
use crate::async_lib::AsyncReadExt;
|
||||||
use crate::content::linkto;
|
use crate::content::linkto;
|
||||||
use crate::errors::{Error, IoErrorExt, Result};
|
use crate::errors::{Error, IoErrorExt, Result};
|
||||||
|
|
@ -8,9 +8,9 @@ use crate::{index, WriteOpts};
|
||||||
use ssri::{Algorithm, Integrity};
|
use ssri::{Algorithm, Integrity};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use std::task::{Context as TaskContext, Poll};
|
use std::task::{Context as TaskContext, Poll};
|
||||||
|
|
||||||
const BUF_SIZE: usize = 16 * 1024;
|
const BUF_SIZE: usize = 16 * 1024;
|
||||||
|
|
@ -30,7 +30,7 @@ const PROBE_SIZE: usize = 8;
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn link_to<P, K, T>(cache: P, key: K, target: T) -> Result<Integrity>
|
pub async fn link_to<P, K, T>(cache: P, key: K, target: T) -> Result<Integrity>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -54,7 +54,7 @@ where
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn link_to_hash<P, T>(cache: P, target: T) -> Result<Integrity>
|
pub async fn link_to_hash<P, T>(cache: P, target: T) -> Result<Integrity>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -110,7 +110,7 @@ where
|
||||||
/// `SyncToLinker` instances.
|
/// `SyncToLinker` instances.
|
||||||
impl WriteOpts {
|
impl WriteOpts {
|
||||||
/// Opens the target file handle for reading, returning a ToLinker instance.
|
/// Opens the target file handle for reading, returning a ToLinker instance.
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn link_to<P, K, T>(self, cache: P, key: K, target: T) -> Result<ToLinker>
|
pub async fn link_to<P, K, T>(self, cache: P, key: K, target: T) -> Result<ToLinker>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -141,7 +141,7 @@ impl WriteOpts {
|
||||||
|
|
||||||
/// Opens the target file handle for reading, without a key, returning a
|
/// Opens the target file handle for reading, without a key, returning a
|
||||||
/// ToLinker instance.
|
/// ToLinker instance.
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn link_to_hash<P, T>(self, cache: P, target: T) -> Result<ToLinker>
|
pub async fn link_to_hash<P, T>(self, cache: P, target: T) -> Result<ToLinker>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -217,7 +217,7 @@ impl WriteOpts {
|
||||||
///
|
///
|
||||||
/// Make sure to call `.commit()` when done reading to actually add the file to
|
/// Make sure to call `.commit()` when done reading to actually add the file to
|
||||||
/// the cache.
|
/// the cache.
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub struct ToLinker {
|
pub struct ToLinker {
|
||||||
cache: PathBuf,
|
cache: PathBuf,
|
||||||
key: Option<String>,
|
key: Option<String>,
|
||||||
|
|
@ -226,7 +226,7 @@ pub struct ToLinker {
|
||||||
opts: WriteOpts,
|
opts: WriteOpts,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
impl AsyncRead for ToLinker {
|
impl AsyncRead for ToLinker {
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
fn poll_read(
|
fn poll_read(
|
||||||
|
|
@ -250,6 +250,17 @@ impl AsyncRead for ToLinker {
|
||||||
self.read += buf.filled().len() - pre_len;
|
self.read += buf.filled().len() - pre_len;
|
||||||
Poll::Ready(Ok(()))
|
Poll::Ready(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
fn poll_read(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut TaskContext<'_>,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Poll<std::io::Result<usize>> {
|
||||||
|
let amt = futures::ready!(Pin::new(&mut self.linker).poll_read(cx, buf))?;
|
||||||
|
self.read += amt;
|
||||||
|
Poll::Ready(Ok(amt))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filesize(target: &Path) -> Result<usize> {
|
fn filesize(target: &Path) -> Result<usize> {
|
||||||
|
|
@ -259,7 +270,7 @@ fn filesize(target: &Path) -> Result<usize> {
|
||||||
.len() as usize)
|
.len() as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
impl ToLinker {
|
impl ToLinker {
|
||||||
/// Creates a new asynchronous readable file handle into the cache.
|
/// Creates a new asynchronous readable file handle into the cache.
|
||||||
pub async fn open<P, K, T>(cache: P, key: K, target: T) -> Result<Self>
|
pub async fn open<P, K, T>(cache: P, key: K, target: T) -> Result<Self>
|
||||||
|
|
@ -493,6 +504,10 @@ mod tests {
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
use async_attributes::test as async_test;
|
use async_attributes::test as async_test;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use macro_rules_attribute::apply;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use smol_macros::test;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
use tokio::test as async_test;
|
use tokio::test as async_test;
|
||||||
|
|
||||||
|
|
@ -520,6 +535,20 @@ mod tests {
|
||||||
assert_eq!(buf, b"hello world");
|
assert_eq!(buf, b"hello world");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn test_link() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let target = create_tmpfile(&tmp, b"hello world");
|
||||||
|
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
crate::link_to(&dir, "my-key", target).await.unwrap();
|
||||||
|
|
||||||
|
let buf = crate::read(&dir, "my-key").await.unwrap();
|
||||||
|
assert_eq!(buf, b"hello world");
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
||||||
#[async_test]
|
#[async_test]
|
||||||
async fn test_link_to_hash() {
|
async fn test_link_to_hash() {
|
||||||
|
|
@ -534,6 +563,20 @@ mod tests {
|
||||||
assert_eq!(buf, b"hello world");
|
assert_eq!(buf, b"hello world");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn test_link_to_hash() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let target = create_tmpfile(&tmp, b"hello world");
|
||||||
|
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let sri = crate::link_to_hash(&dir, target).await.unwrap();
|
||||||
|
|
||||||
|
let buf = crate::read_hash(&dir, &sri).await.unwrap();
|
||||||
|
assert_eq!(buf, b"hello world");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_link_to_sync() {
|
fn test_link_to_sync() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
|
@ -579,6 +622,25 @@ mod tests {
|
||||||
assert_eq!(buf, b"hello world");
|
assert_eq!(buf, b"hello world");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn test_open() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let target = create_tmpfile(&tmp, b"hello world");
|
||||||
|
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let mut handle = crate::ToLinker::open(&dir, "my-key", target).await.unwrap();
|
||||||
|
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
handle.read_to_end(&mut buf).await.unwrap();
|
||||||
|
handle.commit().await.unwrap();
|
||||||
|
assert_eq!(buf, b"hello world");
|
||||||
|
|
||||||
|
let buf = crate::read_sync(&dir, "my-key").unwrap();
|
||||||
|
assert_eq!(buf, b"hello world");
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
||||||
#[async_test]
|
#[async_test]
|
||||||
async fn test_open_hash() {
|
async fn test_open_hash() {
|
||||||
|
|
@ -598,6 +660,25 @@ mod tests {
|
||||||
assert_eq!(buf, b"hello world");
|
assert_eq!(buf, b"hello world");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn test_open_hash() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let target = create_tmpfile(&tmp, b"hello world");
|
||||||
|
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let mut handle = crate::ToLinker::open_hash(&dir, target).await.unwrap();
|
||||||
|
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
handle.read_to_end(&mut buf).await.unwrap();
|
||||||
|
let sri = handle.commit().await.unwrap();
|
||||||
|
assert_eq!(buf, b"hello world");
|
||||||
|
|
||||||
|
let buf = crate::read_hash_sync(&dir, &sri).unwrap();
|
||||||
|
assert_eq!(buf, b"hello world");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_open_sync() {
|
fn test_open_sync() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
|
|
||||||
60
src/put.rs
60
src/put.rs
|
|
@ -1,19 +1,19 @@
|
||||||
//! Functions for writing to cache.
|
//! Functions for writing to cache.
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use ssri::{Algorithm, Integrity};
|
use ssri::{Algorithm, Integrity};
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use crate::async_lib::{AsyncWrite, AsyncWriteExt};
|
use crate::async_lib::{AsyncWrite, AsyncWriteExt};
|
||||||
use crate::content::write;
|
use crate::content::write;
|
||||||
use crate::errors::{Error, IoErrorExt, Result};
|
use crate::errors::{Error, IoErrorExt, Result};
|
||||||
use crate::index;
|
use crate::index;
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
use std::task::{Context as TaskContext, Poll};
|
use std::task::{Context as TaskContext, Poll};
|
||||||
|
|
||||||
/// Writes `data` to the `cache`, indexing it under `key`.
|
/// Writes `data` to the `cache`, indexing it under `key`.
|
||||||
|
|
@ -28,7 +28,7 @@ use std::task::{Context as TaskContext, Poll};
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn write<P, D, K>(cache: P, key: K, data: D) -> Result<Integrity>
|
pub async fn write<P, D, K>(cache: P, key: K, data: D) -> Result<Integrity>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -51,7 +51,7 @@ where
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn write_with_algo<P, D, K>(
|
pub async fn write_with_algo<P, D, K>(
|
||||||
algo: Algorithm,
|
algo: Algorithm,
|
||||||
cache: P,
|
cache: P,
|
||||||
|
|
@ -89,7 +89,7 @@ where
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn write_hash<P, D>(cache: P, data: D) -> Result<Integrity>
|
pub async fn write_hash<P, D>(cache: P, data: D) -> Result<Integrity>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -111,7 +111,7 @@ where
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn write_hash_with_algo<P, D>(algo: Algorithm, cache: P, data: D) -> Result<Integrity>
|
pub async fn write_hash_with_algo<P, D>(algo: Algorithm, cache: P, data: D) -> Result<Integrity>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -132,7 +132,7 @@ where
|
||||||
inner(algo, cache.as_ref(), data.as_ref()).await
|
inner(algo, cache.as_ref(), data.as_ref()).await
|
||||||
}
|
}
|
||||||
/// A reference to an open file writing to the cache.
|
/// A reference to an open file writing to the cache.
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub struct Writer {
|
pub struct Writer {
|
||||||
cache: PathBuf,
|
cache: PathBuf,
|
||||||
key: Option<String>,
|
key: Option<String>,
|
||||||
|
|
@ -141,7 +141,7 @@ pub struct Writer {
|
||||||
opts: WriteOpts,
|
opts: WriteOpts,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
impl AsyncWrite for Writer {
|
impl AsyncWrite for Writer {
|
||||||
fn poll_write(
|
fn poll_write(
|
||||||
mut self: Pin<&mut Self>,
|
mut self: Pin<&mut Self>,
|
||||||
|
|
@ -169,9 +169,14 @@ impl AsyncWrite for Writer {
|
||||||
) -> Poll<std::io::Result<()>> {
|
) -> Poll<std::io::Result<()>> {
|
||||||
Pin::new(&mut self.writer).poll_shutdown(cx)
|
Pin::new(&mut self.writer).poll_shutdown(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
fn poll_close(mut self: Pin<&mut Self>, cx: &mut TaskContext<'_>) -> Poll<std::io::Result<()>> {
|
||||||
|
Pin::new(&mut self.writer).poll_close(cx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
impl Writer {
|
impl Writer {
|
||||||
/// Creates a new writable file handle into the cache.
|
/// Creates a new writable file handle into the cache.
|
||||||
///
|
///
|
||||||
|
|
@ -372,7 +377,7 @@ impl WriteOpts {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Opens the file handle for writing, returning an Writer instance.
|
/// Opens the file handle for writing, returning an Writer instance.
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn open<P, K>(self, cache: P, key: K) -> Result<Writer>
|
pub async fn open<P, K>(self, cache: P, key: K) -> Result<Writer>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -396,7 +401,7 @@ impl WriteOpts {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Opens the file handle for writing, without a key returning an Writer instance.
|
/// Opens the file handle for writing, without a key returning an Writer instance.
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn open_hash<P>(self, cache: P) -> Result<Writer>
|
pub async fn open_hash<P>(self, cache: P) -> Result<Writer>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -607,6 +612,10 @@ impl SyncWriter {
|
||||||
mod tests {
|
mod tests {
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
use async_attributes::test as async_test;
|
use async_attributes::test as async_test;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use macro_rules_attribute::apply;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use smol_macros::test;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
use tokio::test as async_test;
|
use tokio::test as async_test;
|
||||||
|
|
||||||
|
|
@ -620,6 +629,16 @@ mod tests {
|
||||||
assert_eq!(data, b"hello");
|
assert_eq!(data, b"hello");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn round_trip() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
crate::write(&dir, "hello", b"hello").await.unwrap();
|
||||||
|
let data = crate::read(&dir, "hello").await.unwrap();
|
||||||
|
assert_eq!(data, b"hello");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn round_trip_sync() {
|
fn round_trip_sync() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
|
@ -659,4 +678,21 @@ mod tests {
|
||||||
String::from_utf8(bytes).expect("we wrote valid utf8 but did not read valid utf8 back");
|
String::from_utf8(bytes).expect("we wrote valid utf8 but did not read valid utf8 back");
|
||||||
assert_eq!(result, original, "we did not read back what we wrote");
|
assert_eq!(result, original, "we did not read back what we wrote");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn hash_write_async() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let original = format!("hello world{}", 12);
|
||||||
|
let integrity = crate::write_hash(&dir, &original)
|
||||||
|
.await
|
||||||
|
.expect("should be able to write a hash asynchronously");
|
||||||
|
let bytes = crate::read_hash(&dir, &integrity)
|
||||||
|
.await
|
||||||
|
.expect("should be able to read back what we wrote");
|
||||||
|
let result =
|
||||||
|
String::from_utf8(bytes).expect("we wrote valid utf8 but did not read valid utf8 back");
|
||||||
|
assert_eq!(result, original, "we did not read back what we wrote");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
64
src/rm.rs
64
src/rm.rs
|
|
@ -31,7 +31,7 @@ use crate::index;
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn remove<P, K>(cache: P, key: K) -> Result<()>
|
pub async fn remove<P, K>(cache: P, key: K) -> Result<()>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -64,7 +64,7 @@ where
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn remove_hash<P: AsRef<Path>>(cache: P, sri: &Integrity) -> Result<()> {
|
pub async fn remove_hash<P: AsRef<Path>>(cache: P, sri: &Integrity) -> Result<()> {
|
||||||
rm::rm_async(cache.as_ref(), sri).await
|
rm::rm_async(cache.as_ref(), sri).await
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +91,7 @@ pub async fn remove_hash<P: AsRef<Path>>(cache: P, sri: &Integrity) -> Result<()
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
|
||||||
pub async fn clear<P: AsRef<Path>>(cache: P) -> Result<()> {
|
pub async fn clear<P: AsRef<Path>>(cache: P) -> Result<()> {
|
||||||
async fn inner(cache: &Path) -> Result<()> {
|
async fn inner(cache: &Path) -> Result<()> {
|
||||||
for entry in cache
|
for entry in cache
|
||||||
|
|
@ -213,6 +213,10 @@ mod tests {
|
||||||
|
|
||||||
#[cfg(feature = "async-std")]
|
#[cfg(feature = "async-std")]
|
||||||
use async_attributes::test as async_test;
|
use async_attributes::test as async_test;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use macro_rules_attribute::apply;
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
use smol_macros::test;
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
use tokio::test as async_test;
|
use tokio::test as async_test;
|
||||||
|
|
||||||
|
|
@ -234,6 +238,24 @@ mod tests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn test_remove() {
|
||||||
|
futures::executor::block_on(async {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let sri = crate::write(&dir, "key", b"my-data").await.unwrap();
|
||||||
|
|
||||||
|
crate::remove(&dir, "key").await.unwrap();
|
||||||
|
|
||||||
|
let entry = crate::metadata(&dir, "key").await.unwrap();
|
||||||
|
assert_eq!(entry, None);
|
||||||
|
|
||||||
|
let data_exists = crate::exists(&dir, &sri).await;
|
||||||
|
assert!(data_exists);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
||||||
#[async_test]
|
#[async_test]
|
||||||
async fn test_remove_data() {
|
async fn test_remove_data() {
|
||||||
|
|
@ -252,6 +274,24 @@ mod tests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn test_remove_data() {
|
||||||
|
futures::executor::block_on(async {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let sri = crate::write(&dir, "key", b"my-data").await.unwrap();
|
||||||
|
|
||||||
|
crate::remove_hash(&dir, &sri).await.unwrap();
|
||||||
|
|
||||||
|
let entry = crate::metadata(&dir, "key").await.unwrap();
|
||||||
|
assert!(entry.is_some());
|
||||||
|
|
||||||
|
let data_exists = crate::exists(&dir, &sri).await;
|
||||||
|
assert!(!data_exists);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
||||||
#[async_test]
|
#[async_test]
|
||||||
async fn test_clear() {
|
async fn test_clear() {
|
||||||
|
|
@ -270,6 +310,24 @@ mod tests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "smol")]
|
||||||
|
#[apply(test!)]
|
||||||
|
async fn test_clear() {
|
||||||
|
futures::executor::block_on(async {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let dir = tmp.path().to_owned();
|
||||||
|
let sri = crate::write(&dir, "key", b"my-data").await.unwrap();
|
||||||
|
|
||||||
|
crate::clear(&dir).await.unwrap();
|
||||||
|
|
||||||
|
let entry = crate::metadata(&dir, "key").await.unwrap();
|
||||||
|
assert!(entry.is_none());
|
||||||
|
|
||||||
|
let data_exists = crate::exists(&dir, &sri).await;
|
||||||
|
assert!(!data_exists);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_remove_sync() {
|
fn test_remove_sync() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue