1use std::fmt;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11#[non_exhaustive]
12pub enum BackendKind {
13 Cpu,
15 Cuda,
17 Metal,
19 Vulkan,
21}
22
23impl BackendKind {
24 pub fn as_config(self) -> &'static str {
26 match self {
27 Self::Cpu => "cpu",
28 Self::Cuda => "cuda",
29 Self::Metal => "metal",
30 Self::Vulkan => "vulkan",
31 }
32 }
33
34 pub fn from_config(value: &str) -> Option<Self> {
38 match value.to_ascii_lowercase().as_str() {
39 "cpu" => Some(Self::Cpu),
40 "cuda" => Some(Self::Cuda),
41 "metal" => Some(Self::Metal),
42 "vulkan" => Some(Self::Vulkan),
43 _ => None,
44 }
45 }
46}
47
48impl fmt::Display for BackendKind {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 f.write_str(self.as_config())
51 }
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56#[non_exhaustive]
57pub struct BackendDescriptor {
58 pub kind: BackendKind,
60}
61
62impl BackendDescriptor {
63 pub const CPU: Self = Self {
65 kind: BackendKind::Cpu,
66 };
67
68 pub fn new(kind: BackendKind) -> Self {
70 Self { kind }
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn roundtrip() {
80 for k in [
81 BackendKind::Cpu,
82 BackendKind::Cuda,
83 BackendKind::Metal,
84 BackendKind::Vulkan,
85 ] {
86 assert_eq!(BackendKind::from_config(k.as_config()), Some(k));
87 }
88 }
89
90 #[test]
91 fn rejects_unknown() {
92 assert_eq!(BackendKind::from_config("webgpu"), None);
93 assert_eq!(BackendKind::from_config(""), None);
94 }
95
96 #[test]
97 fn is_case_insensitive() {
98 assert_eq!(BackendKind::from_config("CUDA"), Some(BackendKind::Cuda));
99 }
100
101 #[test]
102 fn cpu_descriptor_is_const() {
103 let d = BackendDescriptor::CPU;
104 assert_eq!(d.kind, BackendKind::Cpu);
105 }
106}