1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
extern crate serde_json;
#[macro_use] extern crate failure;
use std::path::{Path, PathBuf};
use std::fs;
use std::io::{self, Read};
use std::ffi;
#[derive(Debug, Fail)]
pub enum Error {
#[fail(display = "I/O error")]
Io(#[cause] io::Error),
#[fail(display = "Failed to read CString from file that contains 0")]
FileContainsNil,
#[fail(display = "Failed get executable path")]
FailedToGetExePath,
}
impl From<io::Error> for Error {
fn from(other: io::Error) -> Self {
Error::Io(other)
}
}
pub struct AssetLoader {
root_path: PathBuf,
}
impl AssetLoader {
pub fn new(rel_path: &Path) -> Result<AssetLoader, Error> {
let exe_file_name = ::std::env::current_exe().map_err(|_| Error::FailedToGetExePath)?;
let exe_path = exe_file_name.parent().ok_or(Error::FailedToGetExePath)?;
Ok(AssetLoader {
root_path: exe_path.join(rel_path)
})
}
pub fn load_cstring(&self, resource_name: &str) -> Result<ffi::CString, Error> {
let mut file = fs::File::open(
resource_name_to_path(&self.root_path, resource_name)
)?;
let mut buffer: Vec<u8> = Vec::with_capacity(
file.metadata()?.len() as usize + 1
);
file.read_to_end(&mut buffer)?;
if buffer.iter().find(|i| **i == 0).is_some() {
return Err(Error::FileContainsNil);
}
Ok(unsafe { ffi::CString::from_vec_unchecked(buffer) })
}
pub fn load_string(&self, resource_name: &str) -> PathBuf {
resource_name_to_path(&self.root_path, resource_name)
}
pub fn load_json(&self, resource_name: &str) -> serde_json::Value {
let mut file = fs::File::open(self.load_string(resource_name)).expect("Unable to load JSON");
let mut data = String::new();
file.read_to_string(&mut data).unwrap();
serde_json::from_str(&data).expect("JSON was not well-formatted")
}
}
fn resource_name_to_path(root_dir: &Path, location: &str) -> PathBuf {
let mut path: PathBuf = root_dir.into();
for part in location.split("/") {
path = path.join(part);
}
path
}