mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
79 lines
2.3 KiB
Rust
79 lines
2.3 KiB
Rust
use std::io;
|
|
|
|
use tokio::{select, sync::mpsc::{self, UnboundedReceiver}};
|
|
use yazi_fs::{File, Files, FilesOp, cha::Cha, mounts::PARTITIONS, provider::{DirReader, FileHolder}};
|
|
use yazi_shared::url::UrlBuf;
|
|
|
|
use crate::{VfsCha, VfsFile, VfsFilesOp, provider::{self, DirEntry}};
|
|
|
|
pub trait VfsFiles {
|
|
fn from_dir(dir: &UrlBuf) -> impl Future<Output = io::Result<UnboundedReceiver<File>>>;
|
|
|
|
fn from_dir_bulk(dir: &UrlBuf) -> impl Future<Output = io::Result<Vec<File>>>;
|
|
|
|
fn assert_stale(dir: &UrlBuf, cha: Cha) -> impl Future<Output = Option<Cha>>;
|
|
}
|
|
|
|
impl VfsFiles for Files {
|
|
async fn from_dir(dir: &UrlBuf) -> std::io::Result<UnboundedReceiver<File>> {
|
|
let mut it = provider::read_dir(dir).await?;
|
|
let (tx, rx) = mpsc::unbounded_channel();
|
|
|
|
tokio::spawn(async move {
|
|
while let Ok(Some(ent)) = it.next().await {
|
|
select! {
|
|
_ = tx.closed() => break,
|
|
result = ent.metadata() => {
|
|
let url = ent.url();
|
|
_ = tx.send(match result {
|
|
Ok(cha) => File::from_follow(url, cha).await,
|
|
Err(_) => File::from_dummy(url, ent.file_type().await.ok())
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
Ok(rx)
|
|
}
|
|
|
|
async fn from_dir_bulk(dir: &UrlBuf) -> std::io::Result<Vec<File>> {
|
|
let mut it = provider::read_dir(dir).await?;
|
|
let mut entries = Vec::new();
|
|
while let Ok(Some(entry)) = it.next().await {
|
|
entries.push(entry);
|
|
}
|
|
|
|
let (first, rest) = entries.split_at(entries.len() / 3);
|
|
let (second, third) = rest.split_at(entries.len() / 3);
|
|
async fn go(entries: &[DirEntry]) -> Vec<File> {
|
|
let mut files = Vec::with_capacity(entries.len());
|
|
for ent in entries {
|
|
let url = ent.url();
|
|
files.push(match ent.metadata().await {
|
|
Ok(cha) => File::from_follow(url, cha).await,
|
|
Err(_) => File::from_dummy(url, ent.file_type().await.ok()),
|
|
});
|
|
}
|
|
files
|
|
}
|
|
|
|
Ok(
|
|
futures::future::join_all([go(first), go(second), go(third)])
|
|
.await
|
|
.into_iter()
|
|
.flatten()
|
|
.collect(),
|
|
)
|
|
}
|
|
|
|
async fn assert_stale(dir: &UrlBuf, cha: Cha) -> Option<Cha> {
|
|
use std::io::ErrorKind;
|
|
match Cha::from_url(dir).await {
|
|
Ok(c) if !c.is_dir() => FilesOp::issue_error(dir, ErrorKind::NotADirectory).await,
|
|
Ok(c) if c.hits(cha) && !PARTITIONS.read().timeless(cha) => {}
|
|
Ok(c) => return Some(c),
|
|
Err(e) => FilesOp::issue_error(dir, e).await,
|
|
}
|
|
None
|
|
}
|
|
}
|