Skip to main content

runmat_package/manifest/
target.rs

1use crate::ManifestError;
2use serde::{Deserialize, Serialize};
3use std::collections::BTreeSet;
4use std::fmt::{Display, Formatter};
5use std::str::FromStr;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
8#[serde(rename_all = "kebab-case")]
9pub enum HostCapability {
10    BrowserFilesystem,
11    Network,
12    WebGpu,
13    Worker,
14    SharedMemory,
15    NativeLibrary,
16    Mex,
17    Jvm,
18    Subprocess,
19}
20
21impl HostCapability {
22    pub const fn as_str(self) -> &'static str {
23        match self {
24            Self::BrowserFilesystem => "browser-filesystem",
25            Self::Network => "network",
26            Self::WebGpu => "webgpu",
27            Self::Worker => "worker",
28            Self::SharedMemory => "shared-memory",
29            Self::NativeLibrary => "native-library",
30            Self::Mex => "mex",
31            Self::Jvm => "jvm",
32            Self::Subprocess => "subprocess",
33        }
34    }
35}
36
37impl Display for HostCapability {
38    fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
39        formatter.write_str(self.as_str())
40    }
41}
42
43impl FromStr for HostCapability {
44    type Err = ManifestError;
45
46    fn from_str(value: &str) -> Result<Self, Self::Err> {
47        match value {
48            "browser-filesystem" => Ok(Self::BrowserFilesystem),
49            "network" => Ok(Self::Network),
50            "webgpu" => Ok(Self::WebGpu),
51            "worker" => Ok(Self::Worker),
52            "shared-memory" => Ok(Self::SharedMemory),
53            "native-library" => Ok(Self::NativeLibrary),
54            "mex" => Ok(Self::Mex),
55            "jvm" => Ok(Self::Jvm),
56            "subprocess" => Ok(Self::Subprocess),
57            _ => Err(ManifestError::InvalidCapability(value.to_string())),
58        }
59    }
60}
61
62#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
63#[serde(tag = "kind", content = "value", rename_all = "kebab-case")]
64pub enum TargetPredicate {
65    Triple(String),
66    Capability(HostCapability),
67}
68
69impl Display for TargetPredicate {
70    fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
71        match self {
72            Self::Triple(triple) => formatter.write_str(triple),
73            Self::Capability(capability) => write!(formatter, "capability:{capability}"),
74        }
75    }
76}
77
78impl FromStr for TargetPredicate {
79    type Err = ManifestError;
80
81    fn from_str(value: &str) -> Result<Self, Self::Err> {
82        let value = value.trim();
83        if let Some(capability) = value.strip_prefix("capability:") {
84            return Ok(Self::Capability(capability.parse()?));
85        }
86        if value.is_empty()
87            || value.chars().any(char::is_whitespace)
88            || value.contains(['/', '\\', ':'])
89        {
90            return Err(ManifestError::InvalidTarget {
91                value: value.to_string(),
92                reason: "expected a normalized target triple or `capability:<name>`".to_string(),
93            });
94        }
95        let segment_count = value.split('-').count();
96        if segment_count < 3 {
97            return Err(ManifestError::InvalidTarget {
98                value: value.to_string(),
99                reason: "target triples must contain at least architecture, vendor, and system"
100                    .to_string(),
101            });
102        }
103        Ok(Self::Triple(value.to_ascii_lowercase()))
104    }
105}
106
107#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
108pub struct TargetEnvironment {
109    pub triple: String,
110    pub capabilities: BTreeSet<HostCapability>,
111}
112
113impl TargetEnvironment {
114    pub fn supports(&self, predicate: &TargetPredicate) -> bool {
115        match predicate {
116            TargetPredicate::Triple(triple) => &self.triple == triple,
117            TargetPredicate::Capability(capability) => self.capabilities.contains(capability),
118        }
119    }
120}