switchyard_protocol/category.rs
1// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Category is a group of models
5
6use std::str::FromStr;
7use std::sync::Arc;
8
9/// A group of models
10#[derive(Clone, Debug, PartialEq, Eq, Hash)]
11pub enum Category {
12 /// When the category doesn't matter: Random, Passthrough, etc.
13 Any,
14 /// High accuracy and cost models.
15 Capable,
16 /// Lower accuracy and cost models.
17 Efficient,
18 /// Models the algorithm can use to decide.
19 Judge,
20 /// A deployment-defined group. Only a custom classifier's policy selects one,
21 /// and no algorithm ascribes meaning to the name.
22 Named(Arc<str>),
23}
24
25impl Category {
26 /// Returns the lowercase category name used in configuration.
27 pub fn as_str(&self) -> &str {
28 match self {
29 Self::Any => "any",
30 Self::Capable => "capable",
31 Self::Efficient => "efficient",
32 Self::Judge => "judge",
33 Self::Named(name) => name,
34 }
35 }
36}
37
38impl FromStr for Category {
39 type Err = String;
40
41 /// The four reserved names are matched first. Were `"capable"` allowed to
42 /// become a [`Category::Named`] there would be two keys that compare unequal
43 /// but print the same, and a lookup of [`Category::Capable`] would silently
44 /// miss the configured group.
45 fn from_str(s: &str) -> Result<Self, Self::Err> {
46 let c = match s {
47 "capable" => Self::Capable,
48 "efficient" => Self::Efficient,
49 "judge" => Self::Judge,
50 "any" => Self::Any,
51 "" => return Err("Category name cannot be empty".to_string()),
52 name => Self::Named(Arc::from(name)),
53 };
54 Ok(c)
55 }
56}