Thinking of reimplementing a filesystem abstraction API

Around 3 months ago I published rialight_filesystem to crates.io: https://crates.io/crates/rialight_filesystem. It's a library that wraps std::fs and, in some ways, std::path. It supports manipulating files in different URI schemes:

  • file:: files on the user device
  • app:: files on the application-installation directory (similiar to Godot Engine's res: assets)
  • app-storage:: files on the application storage directory (for example, cache or cookies)

Note that the way path normalization and resolution were implemented were hand-converted from NodeJS's path implementation to Rust.

Futurely it'd also use web APIs internally for loading files in app: and app-storage: schemes in a special way (e.g. preload all application-installation files through web XMLHttpRequest or fetch).

I'm looking to re-implement this module. I see that people avoided it, what are the reasons? One I think of is:

Instead of NodeJS path implementation, now I guess I'm going to do this:

use rialight_util::AnyStringType;
use lazy_regex::{lazy_regex, Lazy, Regex};

static PATH_SEPARATOR: Lazy<Regex> = lazy_regex!(r"[/\\]");
static STARTS_WITH_PATH_SEPARATOR: Lazy<Regex> = lazy_regex!(r"^[/\\]");

fn resolve_single_path(path: impl AnyStringType) -> String {
    let mut r = Vec::<String>::new();
    for p in PATH_SEPARATOR.split(path.convert()) {
        if p == "." {
            continue;
        } else if p == ".." {
            if r.len() != 0 {
                r.remove(r.len() - 1);
            }
        } else if !p.is_empty() {
            r.push(p.to_owned());
        }
    }
    r.join("/")
}

pub fn resolve_two_paths(path1: impl AnyStringType, path2: impl AnyStringType) -> String {
    if STARTS_WITH_PATH_SEPARATOR.is_match(path2.convert()) {
        #[cfg(target_os = "windows")] {
            return resolve_single_path(path2);
        }
        #[cfg(not(target_os = "windows"))] {
            return "/".to_owned() + &resolve_single_path(path2);
        }
    }
    let path1_resolved = resolve_single_path(path1);
    if path2.convert().is_empty() {
        #[cfg(target_os = "windows")] {
            return path1_resolved;
        }
        #[cfg(not(target_os = "windows"))] {
            return ("/" + &path1_resolved).to_owned();
        }
    }
    let paths_combination = path1_resolved + "/" + path2.convert();
    #[cfg(target_os = "windows")] {
        return resolve_single_path(paths_combination);
    }
    #[cfg(not(target_os = "windows"))] {
        return ("/".to_owned() + &resolve_single_path(paths_combination)).to_owned();
    }
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.