rustc_codegen_spirv_types/target.rs
1use std::fmt::{Debug, Formatter};
2use thiserror::Error;
3
4pub const SPIRV_TARGET_PREFIX: &str = "spirv-unknown-";
5
6/// A well-formed rust-gpu target.
7///
8/// The constructors only check whether the target is well-formed, not whether it is valid. Since `spirv-builder` is
9/// backwards compatible with older rust-gpu compilers, only the compiler itself knows what targets it can and cannot
10/// support. This also allows adding new targets to the compiler without having to update `spirv-builder` and
11/// `cargo-gpu`.
12///
13/// Differentiates between a full target (e.g. `spirv-unknown-vulkan1.3`) and a target env (e.g. `vulkan1.3`). Use
14/// [`Self::parse_target`] and [`Self::target`] to parse or format a full target, or use [`Self::parse_env`] and
15/// [`Self::env`] when dealing with just target envs. The convenience function [`Self::parse`] accepts both targets and
16/// target envs. Does not implement `Display`, since it is unclear whether the user wants a target or target env, though
17/// a `Debug` implementation is provided.
18#[derive(Clone)]
19pub struct SpirvTarget {
20 target: String,
21}
22
23impl SpirvTarget {
24 /// Try to parse either a full target or a target env
25 pub fn parse(target_or_env: &str) -> Result<Self, TargetError> {
26 Self::parse_target(target_or_env).or_else(|_| Self::parse_env(target_or_env))
27 }
28
29 /// Parse a full target, e.g. `spirv-unknown-vulkan1.3`
30 pub fn parse_target(target: &str) -> Result<Self, TargetError> {
31 let _target_env = target.strip_prefix(SPIRV_TARGET_PREFIX).ok_or_else(|| {
32 TargetError::NonSpirvTarget {
33 target: target.to_string(),
34 }
35 })?;
36 Ok(Self {
37 target: target.to_string(),
38 })
39 }
40
41 /// Parse a target env, e.g. `vulkan1.3`
42 pub fn parse_env(target_env: &str) -> Result<Self, TargetError> {
43 Ok(Self {
44 target: format!("{SPIRV_TARGET_PREFIX}{target_env}"),
45 })
46 }
47
48 /// returns the full target, e.g. `spirv-unknown-vulkan1.3`
49 pub fn target(&self) -> &str {
50 &self.target
51 }
52
53 /// returns the target env, e.g. `vulkan1.3`
54 pub fn env(&self) -> &str {
55 &self.target[SPIRV_TARGET_PREFIX.len()..]
56 }
57}
58
59impl Debug for SpirvTarget {
60 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
61 f.debug_tuple("Target").field(&self.target).finish()
62 }
63}
64
65#[derive(Debug, Error)]
66#[non_exhaustive]
67pub enum TargetError {
68 #[error("SPIR-V target must start with `{SPIRV_TARGET_PREFIX}...`, was `{target}`")]
69 NonSpirvTarget { target: String },
70}