1use serde::{Deserialize, Deserializer, Serialize, Serializer};
14use std::fmt;
15
16#[derive(Debug, Clone, PartialEq, Eq, Hash)]
18pub enum MuseModel {
19 Spark13,
21 Spark13Contributor,
24 Spark12,
26 Spark12Contributor,
29 Custom(String),
32}
33
34impl MuseModel {
35 pub fn cli_arg(&self) -> &str {
37 match self {
38 Self::Spark13 => "muse-spark-1.3",
39 Self::Spark13Contributor => "muse-spark-1.3-contributor",
40 Self::Spark12 => "muse-spark-1.2",
41 Self::Spark12Contributor => "muse-spark-1.2-contributor",
42 Self::Custom(s) => s.as_str(),
43 }
44 }
45
46 pub fn as_str(&self) -> &str {
49 self.cli_arg()
50 }
51
52 pub fn display_name(&self) -> &str {
55 self.cli_arg()
56 }
57
58 pub fn context_limit(&self) -> Option<u64> {
61 match self {
62 Self::Spark13 | Self::Spark13Contributor | Self::Spark12 | Self::Spark12Contributor => {
63 Some(1_007_997)
64 }
65 Self::Custom(_) => None,
66 }
67 }
68
69 pub fn output_limit(&self) -> Option<u64> {
72 match self {
73 Self::Spark13 | Self::Spark13Contributor | Self::Spark12 | Self::Spark12Contributor => {
74 Some(128_000)
75 }
76 Self::Custom(_) => None,
77 }
78 }
79
80 pub fn catalog_default() -> Self {
83 Self::Spark13Contributor
84 }
85
86 pub fn known() -> &'static [MuseModel] {
88 &[
89 Self::Spark13,
90 Self::Spark13Contributor,
91 Self::Spark12,
92 Self::Spark12Contributor,
93 ]
94 }
95}
96
97impl fmt::Display for MuseModel {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 f.write_str(self.cli_arg())
100 }
101}
102
103impl From<&str> for MuseModel {
104 fn from(s: &str) -> Self {
105 match s {
106 "muse-spark-1.3" => Self::Spark13,
107 "muse-spark-1.3-contributor" => Self::Spark13Contributor,
108 "muse-spark-1.2" => Self::Spark12,
109 "muse-spark-1.2-contributor" => Self::Spark12Contributor,
110 other => Self::Custom(other.to_string()),
111 }
112 }
113}
114
115impl From<MuseModel> for String {
116 fn from(model: MuseModel) -> Self {
117 model.cli_arg().to_string()
118 }
119}
120
121impl Serialize for MuseModel {
122 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
123 serializer.serialize_str(self.cli_arg())
124 }
125}
126
127impl<'de> Deserialize<'de> for MuseModel {
128 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
129 let s = String::deserialize(deserializer)?;
130 Ok(Self::from(s.as_str()))
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::MuseModel;
137
138 #[test]
139 fn cli_arg_round_trips_for_all_known_models() {
140 for model in MuseModel::known() {
141 assert_eq!(&MuseModel::from(model.cli_arg()), model);
142 }
143 assert_eq!(
144 MuseModel::from("muse-nova-9"),
145 MuseModel::Custom("muse-nova-9".to_string())
146 );
147 }
148
149 #[test]
150 fn catalog_metadata_present_for_known_absent_for_custom() {
151 for model in MuseModel::known() {
152 assert!(model.context_limit().is_some());
153 assert!(model.output_limit().is_some());
154 }
155 assert_eq!(MuseModel::from("muse-nova-9").context_limit(), None);
156 }
157
158 #[test]
159 fn default_is_spark_13_contributor() {
160 assert_eq!(
161 MuseModel::catalog_default().cli_arg(),
162 "muse-spark-1.3-contributor"
163 );
164 }
165}