composio_sdk/models/
versioning.rs1use serde::{Deserialize, Serialize};
27use std::collections::HashMap;
28
29pub const TOOLKIT_LATEST_VERSION: &str = "latest";
31
32#[derive(Debug, Clone, PartialEq, Eq)]
51pub enum ToolkitVersion {
52 Latest,
54 Specific(String),
56}
57
58impl Serialize for ToolkitVersion {
59 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
60 where
61 S: serde::Serializer,
62 {
63 serializer.serialize_str(self.as_str())
64 }
65}
66
67impl<'de> Deserialize<'de> for ToolkitVersion {
68 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
69 where
70 D: serde::Deserializer<'de>,
71 {
72 let s = String::deserialize(deserializer)?;
73 Ok(if s == TOOLKIT_LATEST_VERSION {
74 Self::Latest
75 } else {
76 Self::Specific(s)
77 })
78 }
79}
80
81impl ToolkitVersion {
82 pub fn as_str(&self) -> &str {
96 match self {
97 Self::Latest => TOOLKIT_LATEST_VERSION,
98 Self::Specific(version) => version.as_str(),
99 }
100 }
101
102 pub fn is_latest(&self) -> bool {
113 matches!(self, Self::Latest)
114 }
115
116 pub fn is_specific(&self) -> bool {
127 matches!(self, Self::Specific(_))
128 }
129}
130
131impl Default for ToolkitVersion {
132 fn default() -> Self {
133 Self::Latest
134 }
135}
136
137impl From<&str> for ToolkitVersion {
138 fn from(s: &str) -> Self {
139 if s == TOOLKIT_LATEST_VERSION {
140 Self::Latest
141 } else {
142 Self::Specific(s.to_string())
143 }
144 }
145}
146
147impl From<String> for ToolkitVersion {
148 fn from(s: String) -> Self {
149 if s == TOOLKIT_LATEST_VERSION {
150 Self::Latest
151 } else {
152 Self::Specific(s)
153 }
154 }
155}
156
157pub type ToolkitVersions = HashMap<String, ToolkitVersion>;
172
173#[derive(Debug, Clone, PartialEq)]
198pub enum ToolkitVersionParam {
199 Versions(ToolkitVersions),
201 Latest,
203 None,
205}
206
207impl Serialize for ToolkitVersionParam {
208 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
209 where
210 S: serde::Serializer,
211 {
212 match self {
213 Self::Versions(map) => map.serialize(serializer),
214 Self::Latest => serializer.serialize_str(TOOLKIT_LATEST_VERSION),
215 Self::None => serializer.serialize_none(),
216 }
217 }
218}
219
220impl<'de> Deserialize<'de> for ToolkitVersionParam {
221 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
222 where
223 D: serde::Deserializer<'de>,
224 {
225 use serde::de::{self, Visitor};
226 use std::fmt;
227
228 struct ToolkitVersionParamVisitor;
229
230 impl<'de> Visitor<'de> for ToolkitVersionParamVisitor {
231 type Value = ToolkitVersionParam;
232
233 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
234 formatter.write_str("a string 'latest', a map of versions, or null")
235 }
236
237 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
238 where
239 E: de::Error,
240 {
241 if value == TOOLKIT_LATEST_VERSION {
242 Ok(ToolkitVersionParam::Latest)
243 } else {
244 Err(de::Error::custom(format!(
245 "expected 'latest' but got '{}'",
246 value
247 )))
248 }
249 }
250
251 fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error>
252 where
253 M: de::MapAccess<'de>,
254 {
255 let versions = ToolkitVersions::deserialize(de::value::MapAccessDeserializer::new(map))?;
256 Ok(ToolkitVersionParam::Versions(versions))
257 }
258
259 fn visit_none<E>(self) -> Result<Self::Value, E>
260 where
261 E: de::Error,
262 {
263 Ok(ToolkitVersionParam::None)
264 }
265
266 fn visit_unit<E>(self) -> Result<Self::Value, E>
267 where
268 E: de::Error,
269 {
270 Ok(ToolkitVersionParam::None)
271 }
272 }
273
274 deserializer.deserialize_any(ToolkitVersionParamVisitor)
275 }
276}
277
278impl Default for ToolkitVersionParam {
279 fn default() -> Self {
280 Self::None
281 }
282}
283
284impl ToolkitVersionParam {
285 pub fn is_latest(&self) -> bool {
287 matches!(self, Self::Latest)
288 }
289
290 pub fn is_none(&self) -> bool {
292 matches!(self, Self::None)
293 }
294
295 pub fn is_versions(&self) -> bool {
297 matches!(self, Self::Versions(_))
298 }
299
300 pub fn get_version(&self, toolkit_slug: &str) -> Option<&ToolkitVersion> {
319 match self {
320 Self::Versions(map) => map.get(toolkit_slug),
321 Self::Latest | Self::None => None,
322 }
323 }
324}
325
326#[cfg(test)]
327mod tests {
328 use super::*;
329
330 #[test]
331 fn test_toolkit_version_latest() {
332 let version = ToolkitVersion::Latest;
333 assert_eq!(version.as_str(), "latest");
334 assert!(version.is_latest());
335 assert!(!version.is_specific());
336 }
337
338 #[test]
339 fn test_toolkit_version_specific() {
340 let version = ToolkitVersion::Specific("20250906_01".to_string());
341 assert_eq!(version.as_str(), "20250906_01");
342 assert!(!version.is_latest());
343 assert!(version.is_specific());
344 }
345
346 #[test]
347 fn test_toolkit_version_default() {
348 let version = ToolkitVersion::default();
349 assert!(version.is_latest());
350 }
351
352 #[test]
353 fn test_toolkit_version_from_str() {
354 let latest: ToolkitVersion = "latest".into();
355 assert!(latest.is_latest());
356
357 let specific: ToolkitVersion = "20250906_01".into();
358 assert!(specific.is_specific());
359 assert_eq!(specific.as_str(), "20250906_01");
360 }
361
362 #[test]
363 fn test_toolkit_version_from_string() {
364 let latest: ToolkitVersion = "latest".to_string().into();
365 assert!(latest.is_latest());
366
367 let specific: ToolkitVersion = "20250906_01".to_string().into();
368 assert!(specific.is_specific());
369 }
370
371 #[test]
372 fn test_toolkit_version_serialization() {
373 let latest = ToolkitVersion::Latest;
374 let json = serde_json::to_string(&latest).unwrap();
375 assert_eq!(json, "\"latest\"");
377
378 let specific = ToolkitVersion::Specific("20250906_01".to_string());
379 let json = serde_json::to_string(&specific).unwrap();
380 assert_eq!(json, "\"20250906_01\"");
381 }
382
383 #[test]
384 fn test_toolkit_version_deserialization() {
385 let json = "\"latest\"";
386 let version: ToolkitVersion = serde_json::from_str(json).unwrap();
387 assert!(version.is_latest());
388
389 let json = "\"20250906_01\"";
390 let version: ToolkitVersion = serde_json::from_str(json).unwrap();
391 assert_eq!(version.as_str(), "20250906_01");
392 }
393
394 #[test]
395 fn test_toolkit_versions_map() {
396 let mut versions: ToolkitVersions = HashMap::new();
397 versions.insert("github".to_string(), ToolkitVersion::Latest);
398 versions.insert(
399 "gmail".to_string(),
400 ToolkitVersion::Specific("20250906_01".to_string()),
401 );
402
403 assert_eq!(versions.len(), 2);
404 assert!(versions.get("github").unwrap().is_latest());
405 assert_eq!(
406 versions.get("gmail").unwrap().as_str(),
407 "20250906_01"
408 );
409 }
410
411 #[test]
412 fn test_toolkit_version_param_latest() {
413 let param = ToolkitVersionParam::Latest;
414 assert!(param.is_latest());
415 assert!(!param.is_none());
416 assert!(!param.is_versions());
417 assert_eq!(param.get_version("github"), None);
418 }
419
420 #[test]
421 fn test_toolkit_version_param_none() {
422 let param = ToolkitVersionParam::None;
423 assert!(!param.is_latest());
424 assert!(param.is_none());
425 assert!(!param.is_versions());
426 assert_eq!(param.get_version("github"), None);
427 }
428
429 #[test]
430 fn test_toolkit_version_param_versions() {
431 let mut versions = HashMap::new();
432 versions.insert("github".to_string(), ToolkitVersion::Latest);
433 versions.insert(
434 "gmail".to_string(),
435 ToolkitVersion::Specific("20250906_01".to_string()),
436 );
437
438 let param = ToolkitVersionParam::Versions(versions);
439 assert!(!param.is_latest());
440 assert!(!param.is_none());
441 assert!(param.is_versions());
442
443 assert!(param.get_version("github").unwrap().is_latest());
444 assert_eq!(
445 param.get_version("gmail").unwrap().as_str(),
446 "20250906_01"
447 );
448 assert_eq!(param.get_version("slack"), None);
449 }
450
451 #[test]
452 fn test_toolkit_version_param_default() {
453 let param = ToolkitVersionParam::default();
454 assert!(param.is_none());
455 }
456
457 #[test]
458 fn test_toolkit_version_param_serialization() {
459 let latest = ToolkitVersionParam::Latest;
460 let json = serde_json::to_string(&latest).unwrap();
461 assert_eq!(json, "\"latest\"");
463
464 let none = ToolkitVersionParam::None;
465 let json = serde_json::to_string(&none).unwrap();
466 assert_eq!(json, "null");
468
469 let mut versions = HashMap::new();
470 versions.insert("github".to_string(), ToolkitVersion::Latest);
471 let param = ToolkitVersionParam::Versions(versions);
472 let json = serde_json::to_string(¶m).unwrap();
473 assert!(json.contains("github"));
474 assert!(json.contains("latest"));
475 }
476
477 #[test]
478 fn test_toolkit_version_equality() {
479 let v1 = ToolkitVersion::Latest;
480 let v2 = ToolkitVersion::Latest;
481 assert_eq!(v1, v2);
482
483 let v3 = ToolkitVersion::Specific("20250906_01".to_string());
484 let v4 = ToolkitVersion::Specific("20250906_01".to_string());
485 assert_eq!(v3, v4);
486
487 assert_ne!(v1, v3);
488 }
489
490 #[test]
491 fn test_toolkit_version_clone() {
492 let v1 = ToolkitVersion::Specific("20250906_01".to_string());
493 let v2 = v1.clone();
494 assert_eq!(v1, v2);
495 }
496}