[oden] Time, path searching, game directory
This commit is contained in:
parent
96e95e22ce
commit
26bfcc7a94
8 changed files with 185 additions and 13 deletions
|
|
@ -1,4 +1,6 @@
|
|||
use oden_js::{module::native::NativeModuleBuilder, ContextRef, ValueResult};
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
|
|
@ -69,10 +71,9 @@ impl IoImpl {
|
|||
|
||||
let path = path.to_string();
|
||||
self.thread_pool.execute(Box::new(move || {
|
||||
// TODO: Actually read the path.
|
||||
let path = path;
|
||||
|
||||
let result = std::fs::read(path);
|
||||
let result = resolve_path(&path, &[]).and_then(|p| std::fs::read(p));
|
||||
promise.resolve(move |ctx: &ContextRef| match result {
|
||||
Ok(v) => ctx.new_array_buffer(v),
|
||||
Err(err) => Err(err.into()),
|
||||
|
|
@ -100,3 +101,72 @@ impl IoAPI {
|
|||
Ok(IoAPI {})
|
||||
}
|
||||
}
|
||||
|
||||
fn append_ext(ext: impl AsRef<OsStr>, path: PathBuf) -> PathBuf {
|
||||
let mut os_string: OsString = path.into();
|
||||
os_string.push(".");
|
||||
os_string.push(ext.as_ref());
|
||||
os_string.into()
|
||||
}
|
||||
|
||||
/// Resolve a path to an existing file.
|
||||
pub fn resolve_path(input: &str, extensions: &[&str]) -> std::io::Result<PathBuf> {
|
||||
let mut path = PathBuf::with_capacity(input.len());
|
||||
for segment in input.split('/') {
|
||||
if segment == "." {
|
||||
continue;
|
||||
} else if segment == ".." {
|
||||
if path.parent().is_none() {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidData,
|
||||
format!("{input} contains too many '..'; directory underflow detected"),
|
||||
));
|
||||
}
|
||||
|
||||
path.pop();
|
||||
} else if segment.contains(":") || segment.contains('\\') {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidData,
|
||||
format!("{input} contains invalid characters"),
|
||||
));
|
||||
} else {
|
||||
path.push(segment);
|
||||
}
|
||||
}
|
||||
|
||||
if path.has_root() {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
format!("{input} is absolute"),
|
||||
));
|
||||
}
|
||||
if path.file_name().is_none() {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
format!("{input} refers to a directory"),
|
||||
));
|
||||
}
|
||||
|
||||
for prefix in ["game", "src"] {
|
||||
let mut actual = PathBuf::from(prefix);
|
||||
actual.push(path.clone());
|
||||
//eprintln!("Trying '{}'...", actual.to_string_lossy());
|
||||
match actual.try_exists() {
|
||||
Ok(true) => return Ok(actual),
|
||||
_ => (),
|
||||
}
|
||||
for extension in extensions.iter() {
|
||||
let actual = append_ext(extension, actual.clone());
|
||||
//eprintln!("Trying '{}'...", actual.to_string_lossy());
|
||||
match actual.try_exists() {
|
||||
Ok(true) => return Ok(actual),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
format!("{input} not found or not accessible"),
|
||||
));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue