steamengine_renderer_util/resources/
mod.rs1use fs_extra::dir::get_dir_content;
2use hashbrown::hash_map::HashMap;
3use rayon::prelude::*;
4use std::fs;
5use tracing::*;
6
7#[cfg(feature = "model-resource-manager")]
9pub mod model;
10
11#[cfg(feature = "texture-resource-manager")]
13pub mod texture;
14
15#[derive(PartialEq, Eq, Hash, Debug, Clone)]
17pub struct Identifier {
18 pub root: String,
22 pub group: String,
25 pub id: String,
28}
29impl Identifier {
30 pub fn parse_from_str(id: &str) -> Self {
47 let seg: Vec<&str> = id.splitn(3, "/").collect();
48 if seg.len() < 3 {
49 let root = seg[0].to_owned();
50 let id = seg[1].to_owned();
51 return Self {
52 root,
53 group: String::new(),
54 id,
55 };
56 }
57 let root = seg[0].to_owned();
58 let group = seg[1].to_owned();
59 let id = seg[2].to_owned();
60 Self { root, group, id }
61 }
62 pub fn root(&self) -> String {
63 self.root.clone()
64 }
65 pub fn group(&self) -> String {
66 self.group.clone()
67 }
68 pub fn id(&self) -> String {
69 self.id.clone()
70 }
71 pub fn new(&self, root: &str, group: &str, id: &str) -> Self {
72 Self {
73 root: root.to_owned(),
74 group: group.to_owned(),
75 id: id.to_owned(),
76 }
77 }
78}
79impl std::fmt::Display for Identifier {
80 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81 f.write_str(&format!("{}-{}:{}", self.root(), self.group(), self.id()))
82 }
83}
84
85pub trait ResourceLoader: Send + Sync {
87 type Resource: Send + Sync;
88 type Error: std::error::Error
89 + Send
90 + Sync
91 + 'static
92 + From<std::io::Error>
93 + From<fs_extra::error::Error>;
94 fn load_from_path(&self, path: &str) -> Result<Self::Resource, Self::Error> {
96 let file = fs::read(path)?;
97 self.load_from_bytes(file)
98 }
99 fn load_all(&self, root: &str) -> Result<HashMap<Identifier, Self::Resource>, Self::Error> {
101 let entries = get_dir_content(root)?;
102 let result: HashMap<Identifier, Self::Resource> = entries
103 .files
104 .par_iter()
105 .filter_map(|entry| {
106 debug!(
107 "READ ENTRY \"{}\" WITH RESOURCE LOADER \"{}\"",
108 entry,
109 self.label()
110 );
111 let id = Identifier::parse_from_str(entry);
112 let res = match self.load_from_path(entry) {
113 Ok(res) => res,
114 Err(err) => {
115 error!("Error loading entry in \"{}\" - {}", self.label(), err);
116 return None;
117 }
118 };
119 Some((id, res))
120 })
121 .collect();
122 Ok(result)
123 }
124 fn load_from_bytes(&self, bytes: Vec<u8>) -> Result<Self::Resource, Self::Error>;
126 fn label(&self) -> &'static str;
128}