Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
ventaquil committed Mar 16, 2024
1 parent e4fcf71 commit 9f6294d
Show file tree
Hide file tree
Showing 4 changed files with 597 additions and 6 deletions.
9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,14 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
async-std = { version = "1.12.0", optional = true }
async-trait = { version = "0.1.77", optional = true }
chksum-hash-core = "0.0.0"
futures-lite = { version = "2.2.0", optional = true }
thiserror = "1.0.51"
tokio = { version = "1.36.0", optional = true, features = ["fs", "io-util"] }

[features]
default = []
async-std = ["async-trait", "dep:async-std", "futures-lite"]
tokio = ["async-trait", "dep:tokio", "async-std?/tokio1"]
311 changes: 311 additions & 0 deletions src/async_std.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,311 @@
#[cfg(not(feature = "tokio"))]
use std::path::{Path, PathBuf};

use async_std::fs::{metadata, read_dir, DirEntry, File, ReadDir};
use async_std::io::BufReader;
use async_std::path::{Path as AsyncPath, PathBuf as AsyncPathBuf};
use async_std::stream::StreamExt;
use async_trait::async_trait;
use futures_lite::io::AsyncBufReadExt;

use crate::{AsyncChksumable, Hash, Hashable, Result};

#[async_trait]
impl AsyncChksumable for AsyncPath {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
let metadata = metadata(&self).await?;
if metadata.is_dir() {
read_dir(self).await?.chksum_with(hash).await
} else {
// everything treat as a file when it is not a directory
File::open(self).await?.chksum_with(hash).await
}
}
}

#[async_trait]
impl AsyncChksumable for &AsyncPath {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
let metadata = metadata(&self).await?;
if metadata.is_dir() {
read_dir(self).await?.chksum_with(hash).await
} else {
// everything treat as a file when it is not a directory
File::open(self).await?.chksum_with(hash).await
}
}
}

#[async_trait]
impl AsyncChksumable for &mut AsyncPath {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
let metadata = metadata(&self).await?;
if metadata.is_dir() {
read_dir(self).await?.chksum_with(hash).await
} else {
// everything treat as a file when it is not a directory
File::open(self).await?.chksum_with(hash).await
}
}
}

#[async_trait]
impl AsyncChksumable for AsyncPathBuf {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
self.as_path().chksum_with(hash).await
}
}

#[async_trait]
impl AsyncChksumable for &AsyncPathBuf {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
self.as_path().chksum_with(hash).await
}
}

#[async_trait]
impl AsyncChksumable for &mut AsyncPathBuf {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
self.as_path().chksum_with(hash).await
}
}

#[cfg(not(feature = "tokio"))]
#[async_trait]
impl AsyncChksumable for Path {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
let metadata = metadata(&self).await?;
if metadata.is_dir() {
read_dir(self).await?.chksum_with(hash).await
} else {
// everything treat as a file when it is not a directory
File::open(self).await?.chksum_with(hash).await
}
}
}

#[cfg(not(feature = "tokio"))]
#[async_trait]
impl AsyncChksumable for &Path {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
let metadata = metadata(&self).await?;
if metadata.is_dir() {
read_dir(self).await?.chksum_with(hash).await
} else {
// everything treat as a file when it is not a directory
File::open(self).await?.chksum_with(hash).await
}
}
}

#[cfg(not(feature = "tokio"))]
#[async_trait]
impl AsyncChksumable for &mut Path {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
let metadata = metadata(&self).await?;
if metadata.is_dir() {
read_dir(self).await?.chksum_with(hash).await
} else {
// everything treat as a file when it is not a directory
File::open(self).await?.chksum_with(hash).await
}
}
}

#[cfg(not(feature = "tokio"))]
#[async_trait]
impl AsyncChksumable for PathBuf {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
self.as_path().chksum_with(hash).await
}
}

#[cfg(not(feature = "tokio"))]
#[async_trait]
impl AsyncChksumable for &PathBuf {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
self.as_path().chksum_with(hash).await
}
}

#[cfg(not(feature = "tokio"))]
#[async_trait]
impl AsyncChksumable for &mut PathBuf {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
self.as_path().chksum_with(hash).await
}
}

#[async_trait]
impl AsyncChksumable for File {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
// if self.is_terminal() {
// return Err(Error::IsTerminal);
// }

let mut reader = BufReader::new(self);
loop {
let buffer = reader.fill_buf().await?;
let length = buffer.len();
if length == 0 {
break;
}
buffer.hash_with(hash);
reader.consume(length);
}
Ok(())
}
}

#[async_trait]
impl AsyncChksumable for &File {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
// if self.is_terminal() {
// return Err(Error::IsTerminal);
// }

let mut reader = BufReader::new(self);
loop {
let buffer = reader.fill_buf().await?;
let length = buffer.len();
if length == 0 {
break;
}
buffer.hash_with(hash);
reader.consume(length);
}
Ok(())
}
}

#[async_trait]
impl AsyncChksumable for &mut File {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
// if self.is_terminal() {
// return Err(Error::IsTerminal);
// }

let mut reader = BufReader::new(self);
loop {
let buffer = reader.fill_buf().await?;
let length = buffer.len();
if length == 0 {
break;
}
buffer.hash_with(hash);
reader.consume(length);
}
Ok(())
}
}

#[async_trait]
impl AsyncChksumable for DirEntry {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
self.path().chksum_with(hash).await
}
}

#[async_trait]
impl AsyncChksumable for &DirEntry {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
self.path().chksum_with(hash).await
}
}

#[async_trait]
impl AsyncChksumable for &mut DirEntry {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
self.path().chksum_with(hash).await
}
}

#[async_trait]
impl AsyncChksumable for ReadDir {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
let mut dir_entries = Vec::new();
while let Some(dir_entry) = self.next().await {
dir_entries.push(dir_entry?);
}
dir_entries.sort_by_key(DirEntry::path);
for mut dir_entry in dir_entries {
AsyncChksumable::chksum_with(&mut dir_entry, hash).await?;
}
Ok(())
}
}

#[async_trait]
impl AsyncChksumable for &mut ReadDir {
async fn chksum_with<H>(&mut self, hash: &mut H) -> Result<()>
where
H: Hash + Send,
{
let mut dir_entries = Vec::new();
while let Some(dir_entry) = self.next().await {
dir_entries.push(dir_entry?);
}
dir_entries.sort_by_key(DirEntry::path);
for mut dir_entry in dir_entries {
AsyncChksumable::chksum_with(&mut dir_entry, hash).await?;
}
Ok(())
}
}
Loading

0 comments on commit 9f6294d

Please sign in to comment.