//! Provider de filesystem local. Crate puro: cero dependencia de UI. //! Implementa `yahweh_core::DataProvider` listando hijos de un path con //! `std::fs::read_dir` y leyendo archivos a `Vec` via `tokio::io`. use async_trait::async_trait; use std::fs; use std::io::Cursor; use std::path::Path; use std::pin::Pin; use tokio::io::{AsyncRead, AsyncWrite}; use yahweh_core::{DataProvider, DisplayType, EntityNode}; pub const PROVIDER_ID: &str = "local_fs"; pub struct FileDataProvider; #[async_trait] impl DataProvider for FileDataProvider { fn provider_id(&self) -> String { PROVIDER_ID.to_string() } async fn list_children(&self, parent_id: Option<&str>) -> Result, String> { let path = parent_id.unwrap_or("."); let mut children = Vec::new(); if let Ok(entries) = fs::read_dir(path) { for entry in entries.filter_map(|e| e.ok()) { let path = entry.path(); let name = path .file_name() .unwrap_or_default() .to_string_lossy() .into_owned(); let display_type = if path.is_dir() { DisplayType::Folder } else { DisplayType::File }; children.push(EntityNode { id: path.to_string_lossy().into_owned(), name, display_type, mime_type: None, }); } } Ok(children) } async fn get_read_stream( &self, entity_id: &str, ) -> Result>, String> { let content = fs::read(Path::new(entity_id)).map_err(|e| e.to_string())?; Ok(Box::pin(Cursor::new(content))) } async fn get_write_stream( &self, _entity_id: &str, ) -> Result>, String> { Err("Escritura en streaming no implementada para FS".to_string()) } }