confuse 0.1.0

A fuser-compatible filesystem API facade using Dokan on Windows and fuser elsewhere.
Documentation
use std::collections::BTreeMap;
use std::ffi::OsString;
use std::sync::Mutex;
use std::time::SystemTime;

use confuse::{Errno, FileAttr};

use super::inode::{INode, alloc_ino};

#[derive(Clone, Copy)]
pub(crate) enum NewNodeKind {
    File,
    Directory,
}

pub(crate) fn insert_node(
    inodes: &Mutex<BTreeMap<u64, INode>>, children: &Mutex<BTreeMap<(u64, OsString), u64>>,
    parent: u64, name: OsString, mode: u32, kind: NewNodeKind,
) -> Result<FileAttr, Errno> {
    if children
        .lock()
        .unwrap()
        .contains_key(&(parent, name.clone()))
    {
        return Err(Errno::EEXIST);
    }

    let ino = alloc_ino();
    let node = match kind {
        NewNodeKind::File => INode::new_file(ino, parent, name.clone(), mode as u16),
        NewNodeKind::Directory => INode::new_dir(ino, parent, name.clone(), mode as u16),
    };
    let attr = node.to_attr();

    inodes.lock().unwrap().insert(ino, node);
    children.lock().unwrap().insert((parent, name), ino);
    touch_parent(inodes, parent, kind);
    Ok(attr)
}

fn touch_parent(inodes: &Mutex<BTreeMap<u64, INode>>, parent: u64, kind: NewNodeKind) {
    let now = SystemTime::now();
    if let Some(parent_node) = inodes.lock().unwrap().get_mut(&parent) {
        if matches!(kind, NewNodeKind::Directory) {
            parent_node.nlink += 1;
        }
        parent_node.mtime = now;
        parent_node.ctime = now;
    }
}