tf_asset_loader/
source.rs1use crate::LoaderError;
2use std::fs::read;
3use std::io::ErrorKind;
4use std::path::PathBuf;
5
6pub trait AssetSource {
8 fn has(&self, path: &str) -> Result<bool, LoaderError>;
10
11 fn load(&self, path: &str) -> Result<Option<Vec<u8>>, LoaderError>;
13}
14
15impl AssetSource for PathBuf {
16 fn has(&self, path: &str) -> Result<bool, LoaderError> {
17 Ok(self.join(path).exists())
18 }
19
20 fn load(&self, path: &str) -> Result<Option<Vec<u8>>, LoaderError> {
21 match read(self.join(path)) {
22 Ok(data) => Ok(Some(data)),
23 Err(e) if e.kind() == ErrorKind::NotFound => Ok(None),
24 Err(e) => Err(e.into()),
25 }
26 }
27}
28
29#[cfg(feature = "vpk")]
30mod vdf {
31 use super::AssetSource;
32 use crate::LoaderError;
33 use vpk::VPK;
34
35 impl AssetSource for VPK {
36 fn has(&self, path: &str) -> Result<bool, LoaderError> {
37 Ok(self.tree.contains_key(path))
38 }
39
40 fn load(&self, path: &str) -> Result<Option<Vec<u8>>, LoaderError> {
41 if let Some(entry) = self.tree.get(path) {
42 Ok(Some(entry.get()?.into()))
43 } else {
44 Ok(None)
45 }
46 }
47 }
48}
49
50#[cfg(feature = "bsp")]
51mod vbsp {
52 use super::AssetSource;
53 use crate::LoaderError;
54 use vbsp::Packfile;
55
56 impl AssetSource for Packfile {
57 fn has(&self, path: &str) -> Result<bool, LoaderError> {
58 Ok(self.has(path)?)
59 }
60
61 fn load(&self, path: &str) -> Result<Option<Vec<u8>>, LoaderError> {
62 Ok(self.get(path)?)
63 }
64 }
65}
66
67#[cfg(feature = "zip")]
68mod zip {
69 use super::AssetSource;
70 use crate::LoaderError;
71 use std::io::{Read, Seek};
72 use std::sync::Mutex;
73 use zip::result::ZipError;
74 use zip::ZipArchive;
75
76 impl<Reader: Read + Seek> AssetSource for Mutex<ZipArchive<Reader>> {
77 fn has(&self, path: &str) -> Result<bool, LoaderError> {
78 match self.lock().unwrap().by_name(path) {
79 Ok(_) => Ok(true),
80 Err(ZipError::FileNotFound) => Ok(false),
81 Err(e) => Err(e.into()),
82 }
83 }
84
85 fn load(&self, path: &str) -> Result<Option<Vec<u8>>, LoaderError> {
86 let mut zip = self.lock().unwrap();
87 let mut entry = match zip.by_name(path) {
88 Ok(entry) => entry,
89 Err(ZipError::FileNotFound) => {
90 return Ok(None);
91 }
92 Err(e) => {
93 return Err(e.into());
94 }
95 };
96 let mut buff = vec![0; entry.size() as usize];
97 entry.read_exact(&mut buff)?;
98 Ok(Some(buff))
99 }
100 }
101}