use std::sync::Arc;
use async_trait::async_trait;
use futures::StreamExt;
use futures::stream::BoxStream;
use vortex_error::VortexResult;
use crate::VortexReadAt;
use crate::filesystem::FileListing;
use crate::filesystem::FileSystem;
use crate::filesystem::FileSystemRef;
#[derive(Debug)]
pub struct PrefixFileSystem {
inner: FileSystemRef,
prefix: String,
}
impl PrefixFileSystem {
pub fn new(inner: FileSystemRef, prefix: String) -> Self {
let prefix = format!("{}/", prefix.trim_matches('/'));
Self { inner, prefix }
}
}
#[async_trait]
impl FileSystem for PrefixFileSystem {
fn list(&self, prefix: &str) -> BoxStream<'_, VortexResult<FileListing>> {
let full_prefix = format!("{}{}", self.prefix, prefix.trim_start_matches('/'));
let strip_prefix = self.prefix.clone();
self.inner
.list(&full_prefix)
.map(move |result| {
result.map(|mut listing| {
listing.path = listing
.path
.strip_prefix(&strip_prefix)
.unwrap_or(&listing.path)
.to_string();
listing
})
})
.boxed()
}
async fn open_read(&self, path: &str) -> VortexResult<Arc<dyn VortexReadAt>> {
self.inner
.open_read(&format!("{}{}", self.prefix, path.trim_start_matches('/')))
.await
}
}
impl dyn FileSystem + 'static {
pub fn with_prefix(self: Arc<Self>, prefix: String) -> FileSystemRef {
Arc::new(PrefixFileSystem::new(self, prefix))
}
}