directory_tree/
lib.rs

1#![feature(trait_alias)]
2
3use neon::prelude::*;
4use serde::Serialize;
5use serde_json;
6use std::fs::{canonicalize, metadata, read_dir, Metadata};
7use std::io::Result;
8use std::path::Path;
9
10#[derive(Serialize, Debug)]
11pub struct FileNode {
12    /// 文件名称
13    name: String,
14
15    /// 绝对路径
16    path: String,
17
18    /// 文件大小
19    size: u64,
20
21    /// 子目录
22    children: Vec<FileNode>,
23}
24
25fn walk(dir: &Path) -> Result<FileNode> {
26    let mut root: FileNode = path2node(&dir)?;
27    if dir.is_dir() {
28        for entry in read_dir(dir)? {
29            let entry = entry?;
30            let path = entry.path();
31
32            if path.is_dir() {
33                root.children.push(walk(&path)?);
34            } else {
35                let child = path2node(&entry.path())?;
36                root.children.push(child);
37            }
38        }
39    }
40    Ok(root)
41}
42
43fn path2node(path: &Path) -> Result<FileNode> {
44    let path = &canonicalize(path)?;
45    let data: Metadata = metadata(&path)?;
46    let node = FileNode {
47        name: path.file_name().unwrap().to_string_lossy().to_string(),
48        path: path.to_string_lossy().to_string(),
49        size: data.len(),
50        children: Vec::new(),
51    };
52
53    Ok(node)
54}
55
56pub fn filetree(path: &Path) -> Result<FileNode> {
57    let root = walk(path)?;
58    Ok(root)
59}
60
61fn hello(mut cx: FunctionContext) -> JsResult<JsString> {
62    Ok(cx.string("hello node"))
63}
64
65#[neon::main]
66fn main(mut cx: ModuleContext) -> NeonResult<()> {
67    cx.export_function("hello", hello)?;
68    Ok(())
69}
70
71#[test]
72fn test_output() {
73    let tree = filetree(Path::new("./node_modules")).unwrap();
74    println!("{}", serde_json::to_string(&tree).unwrap());
75}