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 name: String,
14
15 path: String,
17
18 size: u64,
20
21 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}