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
use std::{
    ops::{Deref, DerefMut},
    path::{Path, PathBuf},
};

use crate::api::{ResourceIdentifier, ResourceKind};

/// Represents the full path to a resource, e.g., on the local file system.
pub struct ResourcePath(PathBuf);

impl ResourcePath {
    /// Returns the full path to the given resource.
    ///
    /// The `root` argument should be the path to the directory containing the
    /// `assets/` and (optionally) `data/` directories.
    ///
    /// **NOTE:** no validation of the path is performed. The returned path may
    /// not point to an existing file. This method simply computes what the path
    /// should be for a given resource.
    pub fn for_resource(root: impl AsRef<Path>, resource: &ResourceIdentifier) -> Self {
        let mut path = Self::for_kind(root, resource.namespace(), resource.kind());

        path.push(resource.path());

        Self(path.with_extension(resource.kind().extension()))
    }

    /// Returns the full path to the directory that contains resources of the
    /// given type for the given namespace.
    ///
    /// The `root` argument should be the path to the directory containing the
    /// `assets/` and (optionally) `data/` directories.
    ///
    /// **NOTE:** no validation of the path is performed. The returned path may
    /// not point to an existing directory. This method simply computes what the
    /// path should be for a given resource type.
    pub fn for_kind(root: impl AsRef<Path>, namespace: &str, kind: ResourceKind) -> Self {
        let mut path = PathBuf::from(root.as_ref());

        // `assets/` or `data/`.
        path.push(kind.category().directory());
        path.push(namespace);
        path.push(kind.directory());

        Self(path)
    }

    /// Consumes `self` and returns the inner [`PathBuf`].
    pub fn into_inner(self) -> PathBuf {
        self.0
    }
}

impl AsRef<Path> for ResourcePath {
    fn as_ref(&self) -> &Path {
        self.0.as_ref()
    }
}

impl Deref for ResourcePath {
    type Target = PathBuf;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for ResourcePath {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}