use std::fmt::{Debug, Formatter};
use thiserror::Error;
pub const SPIRV_ARCH: &str = "spirv";
pub const SPIRV_TARGET_PREFIX: &str = "spirv-unknown-";
#[derive(Clone)]
pub struct SpirvTarget {
target: String,
}
impl SpirvTarget {
pub fn parse(target_or_env: &str) -> Result<Self, TargetError> {
Self::parse_target(target_or_env).or_else(|_| Self::parse_env(target_or_env))
}
pub fn parse_target(target: &str) -> Result<Self, TargetError> {
let _target_env = target.strip_prefix(SPIRV_TARGET_PREFIX).ok_or_else(|| {
TargetError::NonSpirvTarget {
target: target.to_string(),
}
})?;
Ok(Self {
target: target.to_string(),
})
}
pub fn parse_env(target_env: &str) -> Result<Self, TargetError> {
Ok(Self {
target: format!("{SPIRV_TARGET_PREFIX}{target_env}"),
})
}
pub fn target(&self) -> &str {
&self.target
}
pub fn env(&self) -> &str {
&self.target[SPIRV_TARGET_PREFIX.len()..]
}
}
impl Debug for SpirvTarget {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Target").field(&self.target).finish()
}
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum TargetError {
#[error("SPIR-V target must start with `{SPIRV_TARGET_PREFIX}...`, was `{target}`")]
NonSpirvTarget { target: String },
}