python_packaging/
location.rs

1// Copyright 2022 Gregory Szorc.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9/*! Functionality related to resource locations. */
10
11/// Describes the location of a Python resource.
12///
13/// The location is abstract because a concrete location (such as the
14/// relative path) is not specified.
15#[derive(Clone, Debug, PartialEq, Eq)]
16pub enum AbstractResourceLocation {
17    /// Resource is loaded from memory.
18    InMemory,
19    /// Resource is loaded from a relative filesystem path.
20    RelativePath,
21}
22
23impl ToString for &AbstractResourceLocation {
24    fn to_string(&self) -> String {
25        match self {
26            AbstractResourceLocation::InMemory => "in-memory".to_string(),
27            AbstractResourceLocation::RelativePath => "filesystem-relative".to_string(),
28        }
29    }
30}
31
32impl TryFrom<&str> for AbstractResourceLocation {
33    type Error = String;
34
35    fn try_from(value: &str) -> Result<Self, Self::Error> {
36        match value {
37            "in-memory" => Ok(Self::InMemory),
38            "filesystem-relative" => Ok(Self::RelativePath),
39            _ => Err(format!("{} is not a valid resource location", value)),
40        }
41    }
42}
43
44/// Describes the concrete location of a Python resource.
45#[derive(Clone, Debug, PartialEq, Eq)]
46pub enum ConcreteResourceLocation {
47    /// Resource is loaded from memory.
48    InMemory,
49    /// Reosurce is loaded from a relative filesystem path.
50    RelativePath(String),
51}
52
53impl From<&ConcreteResourceLocation> for AbstractResourceLocation {
54    fn from(l: &ConcreteResourceLocation) -> Self {
55        match l {
56            ConcreteResourceLocation::InMemory => AbstractResourceLocation::InMemory,
57            ConcreteResourceLocation::RelativePath(_) => AbstractResourceLocation::RelativePath,
58        }
59    }
60}
61
62impl ToString for ConcreteResourceLocation {
63    fn to_string(&self) -> String {
64        match self {
65            ConcreteResourceLocation::InMemory => "in-memory".to_string(),
66            ConcreteResourceLocation::RelativePath(prefix) => {
67                format!("filesystem-relative:{}", prefix)
68            }
69        }
70    }
71}
72
73impl From<ConcreteResourceLocation> for String {
74    fn from(location: ConcreteResourceLocation) -> Self {
75        location.to_string()
76    }
77}
78
79impl TryFrom<&str> for ConcreteResourceLocation {
80    type Error = String;
81
82    fn try_from(value: &str) -> Result<Self, Self::Error> {
83        if value == "in-memory" {
84            Ok(Self::InMemory)
85        } else {
86            let parts = value.splitn(2, ':').collect::<Vec<_>>();
87
88            if parts.len() != 2 {
89                Err(format!("{} is not a valid resource location", value))
90            } else {
91                let prefix = parts[0];
92                let suffix = parts[1];
93
94                if prefix == "filesystem-relative" {
95                    Ok(Self::RelativePath(suffix.to_string()))
96                } else {
97                    Err(format!("{} is not a valid resource location", value))
98                }
99            }
100        }
101    }
102}
103
104#[cfg(test)]
105mod tests {
106    use {super::*, anyhow::Result};
107
108    #[test]
109    fn test_abstract_from_string() -> Result<()> {
110        assert_eq!(
111            AbstractResourceLocation::try_from("in-memory"),
112            Ok(AbstractResourceLocation::InMemory)
113        );
114        assert_eq!(
115            AbstractResourceLocation::try_from("filesystem-relative"),
116            Ok(AbstractResourceLocation::RelativePath)
117        );
118
119        Ok(())
120    }
121
122    #[test]
123    fn test_concrete_from_string() -> Result<()> {
124        assert_eq!(
125            ConcreteResourceLocation::try_from("in-memory"),
126            Ok(ConcreteResourceLocation::InMemory)
127        );
128        assert_eq!(
129            ConcreteResourceLocation::try_from("filesystem-relative:lib"),
130            Ok(ConcreteResourceLocation::RelativePath("lib".to_string()))
131        );
132
133        Ok(())
134    }
135}