smart-tree 8.0.1

Smart Tree - An intelligent, AI-friendly directory visualization tool
Documentation
//! Traditional file system input adapter

use super::*;
use anyhow::Result;
use async_trait::async_trait;
use std::fs;

pub struct FileSystemAdapter;

#[async_trait]
impl InputAdapter for FileSystemAdapter {
    fn name(&self) -> &'static str {
        "FileSystem"
    }

    fn supported_formats(&self) -> Vec<&'static str> {
        vec!["dir", "directory", "folder", "path"]
    }

    async fn can_handle(&self, input: &InputSource) -> bool {
        match input {
            InputSource::Path(path) => path.exists(),
            _ => false,
        }
    }

    async fn parse(&self, input: InputSource) -> Result<ContextNode> {
        match input {
            InputSource::Path(path) => {
                let metadata = fs::metadata(&path)?;
                let name = path
                    .file_name()
                    .and_then(|n| n.to_str())
                    .unwrap_or("root")
                    .to_string();

                let mut root = ContextNode {
                    id: path.to_string_lossy().to_string(),
                    name,
                    node_type: if metadata.is_dir() {
                        NodeType::Directory
                    } else {
                        NodeType::File
                    },
                    quantum_state: None,
                    children: vec![],
                    metadata: serde_json::json!({
                        "size": metadata.len(),
                        "modified": metadata.modified().ok(),
                        "readonly": metadata.permissions().readonly(),
                    }),
                    entanglements: vec![],
                };

                if metadata.is_dir() {
                    root.children = self.scan_directory(&path)?;
                }

                Ok(root)
            }
            _ => anyhow::bail!("FileSystem adapter only handles Path inputs"),
        }
    }
}

impl FileSystemAdapter {
    #[allow(clippy::only_used_in_recursion)]
    fn scan_directory(&self, path: &std::path::Path) -> Result<Vec<ContextNode>> {
        let mut nodes = Vec::new();

        for entry in fs::read_dir(path)? {
            let entry = entry?;
            let path = entry.path();
            let metadata = entry.metadata()?;

            let node = ContextNode {
                id: path.to_string_lossy().to_string(),
                name: entry.file_name().to_string_lossy().to_string(),
                node_type: if metadata.is_dir() {
                    NodeType::Directory
                } else {
                    NodeType::File
                },
                quantum_state: None,
                children: if metadata.is_dir() {
                    self.scan_directory(&path).unwrap_or_default()
                } else {
                    vec![]
                },
                metadata: serde_json::json!({
                    "size": metadata.len(),
                    "modified": metadata.modified().ok(),
                }),
                entanglements: vec![],
            };

            nodes.push(node);
        }

        Ok(nodes)
    }
}