1use std::str::FromStr;
2
3use kcl_error::KclError;
4use kcl_error::KclErrorDetails;
5use serde::Deserialize;
6use serde::Serialize;
7
8#[derive(
10 Debug, Clone, Copy, Default, Deserialize, Serialize, PartialEq, Eq, Ord, PartialOrd, schemars::JsonSchema, ts_rs::TS,
11)]
12#[ts(export)]
13pub enum KclVersion {
14 #[default]
16 #[serde(rename = "1.0")]
17 V1,
18 #[serde(rename = "2.0")]
21 V2,
22 #[serde(rename = "3.0-preview")]
24 V3Preview,
25 }
28
29impl KclVersion {
30 pub fn as_str(self) -> &'static str {
32 match self {
33 Self::V1 => "1.0",
34 Self::V2 => "2.0",
35 Self::V3Preview => "3.0-preview",
36 }
37 }
38}
39
40#[derive(Debug, Eq, PartialEq, Clone, Copy)]
41pub struct KclVersionError;
42
43impl core::error::Error for KclVersionError {}
44
45impl std::fmt::Display for KclVersionError {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 write!(
48 f,
49 "Unrecognized version. Valid versions are 1.0, 2.0 and (experimentally) 3.0-preview"
50 )
51 }
52}
53
54impl FromStr for KclVersion {
55 type Err = KclVersionError;
56
57 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
58 match s {
59 "1" | "1.0" | "1.0.0" => Ok(Self::V1),
60 "2" | "2.0" | "2.0.0" => Ok(Self::V2),
61 "3-preview" | "3.0-preview" | "3.0.0-preview" => Ok(Self::V3Preview),
62 _other => Err(KclVersionError),
63 }
64 }
65}
66
67impl From<KclVersionError> for KclError {
68 fn from(e: KclVersionError) -> Self {
69 Self::Semantic {
70 details: KclErrorDetails {
71 source_ranges: Default::default(),
72 backtrace: Default::default(),
73 message: e.to_string(),
74 },
75 }
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn roundtrip_str() {
85 for input in [KclVersion::V1, KclVersion::V2, KclVersion::V3Preview] {
86 let serialized = input.as_str();
87 let deserialized: KclVersion = serialized.parse().unwrap();
88 assert_eq!(input, deserialized);
89 }
90 }
91
92 #[test]
93 fn kcl_version_parses_supported_spellings() {
94 assert_eq!(KclVersion::from_str("1"), Ok(KclVersion::V1));
95 assert_eq!(KclVersion::from_str("1.0.0"), Ok(KclVersion::V1));
96 assert_eq!(KclVersion::from_str("2"), Ok(KclVersion::V2));
97 assert_eq!(KclVersion::from_str("2.0.0"), Ok(KclVersion::V2));
98 assert_eq!(KclVersion::from_str("3.0-preview"), Ok(KclVersion::V3Preview));
99 KclVersion::from_str("99.123").unwrap_err();
101 }
102}