1use serde::{Deserialize, Deserializer, Serialize};
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
6#[serde(rename_all = "lowercase")]
7pub enum LanguageType {
8 Data,
9 Programming,
10 Markup,
11 Prose,
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct Language {
17 #[serde(rename = "type")]
19 pub language_type: LanguageType,
20
21 pub ace_mode: String,
23
24 pub tm_scope: String,
26
27 pub language_id: i64,
29
30 #[serde(default, skip_serializing_if = "Option::is_none")]
32 pub extensions: Option<Vec<String>>,
33
34 #[serde(default, skip_serializing_if = "Option::is_none")]
36 pub filenames: Option<Vec<String>>,
37
38 #[serde(default, skip_serializing_if = "Option::is_none")]
40 pub aliases: Option<Vec<String>>,
41
42 #[serde(default, skip_serializing_if = "Option::is_none")]
44 pub interpreters: Option<Vec<String>>,
45
46 #[serde(default, skip_serializing_if = "Option::is_none")]
48 pub color: Option<String>,
49
50 #[serde(default, skip_serializing_if = "Option::is_none")]
52 pub codemirror_mode: Option<String>,
53
54 #[serde(default, skip_serializing_if = "Option::is_none")]
56 pub codemirror_mime_type: Option<String>,
57
58 #[serde(default, skip_serializing_if = "Option::is_none")]
60 pub group: Option<String>,
61
62 #[serde(default, skip_serializing_if = "Option::is_none")]
64 pub fs_name: Option<String>,
65
66 #[serde(default, skip_serializing_if = "Option::is_none")]
68 pub wrap: Option<bool>,
69}
70
71pub type Languages = HashMap<String, Language>;
74
75fn deserialize_optional_string_or_vec<'de, D>(
81 deserializer: D,
82) -> Result<Option<Vec<String>>, D::Error>
83where
84 D: Deserializer<'de>,
85{
86 #[derive(Deserialize)]
87 #[serde(untagged)]
88 enum StringOrVec {
89 Single(String),
90 Multiple(Vec<String>),
91 }
92
93 Ok(Some(match Option::<StringOrVec>::deserialize(deserializer)? {
94 None => return Ok(None),
95 Some(StringOrVec::Single(s)) => vec![s],
96 Some(StringOrVec::Multiple(v)) => v,
97 }))
98}
99
100fn deserialize_hashmap_string_or_vec<'de, D>(
102 deserializer: D,
103) -> Result<HashMap<String, Vec<String>>, D::Error>
104where
105 D: Deserializer<'de>,
106{
107 #[derive(Deserialize)]
108 #[serde(untagged)]
109 enum StringOrVec {
110 Single(String),
111 Multiple(Vec<String>),
112 }
113
114 let map = HashMap::<String, StringOrVec>::deserialize(deserializer)?;
115 Ok(map
116 .into_iter()
117 .map(|(k, v)| match v {
118 StringOrVec::Single(s) => (k, vec![s]),
119 StringOrVec::Multiple(v) => (k, v),
120 })
121 .collect())
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct HeuristicRule {
127 #[serde(
129 default,
130 skip_serializing_if = "Option::is_none",
131 deserialize_with = "deserialize_optional_string_or_vec"
132 )]
133 pub language: Option<Vec<String>>,
134
135 #[serde(
137 default,
138 skip_serializing_if = "Option::is_none",
139 deserialize_with = "deserialize_optional_string_or_vec"
140 )]
141 pub pattern: Option<Vec<String>>,
142
143 #[serde(
145 default,
146 skip_serializing_if = "Option::is_none",
147 deserialize_with = "deserialize_optional_string_or_vec"
148 )]
149 pub negative_pattern: Option<Vec<String>>,
150
151 #[serde(default, skip_serializing_if = "Option::is_none")]
153 pub named_pattern: Option<String>,
154
155 #[serde(default, skip_serializing_if = "Option::is_none")]
157 pub and: Option<Vec<HeuristicRule>>,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct Disambiguation {
163 pub extensions: Vec<String>,
165
166 pub rules: Vec<HeuristicRule>,
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct Heuristics {
173 pub disambiguations: Vec<Disambiguation>,
175
176 #[serde(deserialize_with = "deserialize_hashmap_string_or_vec")]
178 pub named_patterns: HashMap<String, Vec<String>>,
179}
180
181pub type VendorPatterns = Vec<String>;