tmx/
loader.rs

1use std::path::{Component, Path, PathBuf};
2use std::sync::Arc;
3
4use anyhow::*;
5
6use crate::Map;
7
8#[derive(Clone)]
9pub(crate) struct TmxLoadContext<'a> {
10    relative: Arc<Path>,
11    lifetime: &'a (),
12}
13
14impl<'a> TmxLoadContext<'a> {
15    pub fn load_file<'p>(&'p self, path: impl AsRef<Path> + Send + 'p) -> Result<Vec<u8>> {
16        Ok(std::fs::read(self.file_path(path))?)
17    }
18
19    pub fn file_path(&self, path: impl AsRef<Path>) -> PathBuf {
20        let mut joined = PathBuf::new();
21        for c in self.relative.join(path.as_ref()).components() {
22            match c {
23                Component::Prefix(prefix) => joined.push(prefix.as_os_str()),
24                Component::RootDir => joined.push("/"),
25                Component::CurDir => (),
26                Component::ParentDir => {
27                    joined.pop();
28                }
29                Component::Normal(c) => joined.push(c),
30            }
31        }
32        joined
33    }
34
35    pub fn file_directory(&self, path: impl AsRef<Path>) -> Self {
36        Self {
37            relative: if let Some(parent) = path.as_ref().parent() {
38                Arc::from(self.relative.join(parent))
39            } else {
40                self.relative.clone()
41            },
42            lifetime: self.lifetime,
43        }
44    }
45}
46
47/// Load Map from a file.
48pub fn load_from_file<P: AsRef<Path>>(path: P) -> Result<Map> {
49    let path = path.as_ref();
50    let context = ();
51    let context = if let Some(parent) = path.parent() {
52        TmxLoadContext {
53            relative: Arc::from(parent.to_path_buf()),
54            lifetime: &context,
55        }
56    } else {
57        TmxLoadContext {
58            relative: Path::new(".").to_path_buf().into(),
59            lifetime: &context,
60        }
61    };
62
63    let reader = xml::EventReader::new(std::fs::File::open(path)?);
64
65    Map::load_from_xml_reader(context, reader)
66}