mcpls_core/config/
language_id.rs1use std::borrow::Cow;
4
5use schemars::{JsonSchema, Schema, SchemaGenerator};
6use serde::{Deserialize, Serialize};
7
8use super::text_newtype::impl_text_newtype;
9
10#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)]
12#[error("language_id cannot be blank")]
13pub struct InvalidLanguageId;
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
29#[serde(try_from = "String", into = "String")]
30pub struct LanguageId(Cow<'static, str>);
31
32impl LanguageId {
33 pub const PLAINTEXT: Self = Self::from_static("plaintext");
35}
36
37impl JsonSchema for LanguageId {
38 fn inline_schema() -> bool {
39 true
40 }
41
42 fn schema_name() -> Cow<'static, str> {
43 Cow::Borrowed("LanguageId")
44 }
45
46 fn json_schema(_generator: &mut SchemaGenerator) -> Schema {
47 schemars::json_schema!({"type": "string"})
48 }
49}
50
51impl_text_newtype!(LanguageId, InvalidLanguageId, non_blank, "language_id");
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[derive(Debug, Serialize, Deserialize, PartialEq)]
58 struct Holder {
59 id: LanguageId,
60 }
61
62 #[test]
63 fn test_rejects_empty() {
64 assert_eq!(LanguageId::new(""), Err(InvalidLanguageId));
65 assert!("".parse::<LanguageId>().is_err());
66 }
67
68 #[test]
69 #[should_panic(expected = "language_id must be ASCII and not blank")]
70 fn test_from_static_panics_on_empty() {
71 let _ = LanguageId::from_static("");
72 }
73
74 #[test]
75 #[should_panic(expected = "language_id must be ASCII and not blank")]
76 fn test_from_static_panics_on_non_ascii_blank() {
77 let _ = LanguageId::from_static("\u{a0}");
78 }
79
80 #[test]
81 fn test_rejects_whitespace_only() {
82 assert_eq!(LanguageId::new(" \u{a0}"), Err(InvalidLanguageId));
83 }
84
85 #[test]
86 fn test_round_trip_and_comparisons() {
87 let holder: Holder = toml::from_str(r#"id = "python""#).unwrap();
88 assert_eq!(holder.id, "python");
89 assert_eq!(holder.id, *"python");
90 assert_eq!(holder.id.to_string(), "python");
91 assert_eq!(holder.id, LanguageId::from_static("python"));
92 let text = toml::to_string(&holder).unwrap();
93 assert_eq!(toml::from_str::<Holder>(&text).unwrap(), holder);
94 }
95
96 #[test]
97 fn test_schema_is_an_inline_string() {
98 let mut generator = SchemaGenerator::default();
99 let schema = LanguageId::json_schema(&mut generator);
100 assert_eq!(schema.as_value(), &serde_json::json!({"type": "string"}));
101 }
102
103 #[test]
104 fn test_hash_lookup_by_str() {
105 let mut map = std::collections::HashMap::new();
106 map.insert(LanguageId::from_static("go"), 1);
107 assert_eq!(map.get("go"), Some(&1));
108 }
109}