use serde::{Deserialize, Deserializer, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum LanguageType {
Data,
Programming,
Markup,
Prose,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Language {
#[serde(rename = "type")]
pub language_type: LanguageType,
pub ace_mode: String,
pub tm_scope: String,
pub language_id: i64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub filenames: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub aliases: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub interpreters: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub color: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub codemirror_mode: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub codemirror_mime_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub group: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub fs_name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wrap: Option<bool>,
}
pub type Languages = HashMap<String, Language>;
fn deserialize_optional_string_or_vec<'de, D>(
deserializer: D,
) -> Result<Option<Vec<String>>, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(untagged)]
enum StringOrVec {
Single(String),
Multiple(Vec<String>),
}
Ok(Some(match Option::<StringOrVec>::deserialize(deserializer)? {
None => return Ok(None),
Some(StringOrVec::Single(s)) => vec![s],
Some(StringOrVec::Multiple(v)) => v,
}))
}
fn deserialize_hashmap_string_or_vec<'de, D>(
deserializer: D,
) -> Result<HashMap<String, Vec<String>>, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(untagged)]
enum StringOrVec {
Single(String),
Multiple(Vec<String>),
}
let map = HashMap::<String, StringOrVec>::deserialize(deserializer)?;
Ok(map
.into_iter()
.map(|(k, v)| match v {
StringOrVec::Single(s) => (k, vec![s]),
StringOrVec::Multiple(v) => (k, v),
})
.collect())
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HeuristicRule {
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_optional_string_or_vec"
)]
pub language: Option<Vec<String>>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_optional_string_or_vec"
)]
pub pattern: Option<Vec<String>>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_optional_string_or_vec"
)]
pub negative_pattern: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub named_pattern: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub and: Option<Vec<HeuristicRule>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Disambiguation {
pub extensions: Vec<String>,
pub rules: Vec<HeuristicRule>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Heuristics {
pub disambiguations: Vec<Disambiguation>,
#[serde(deserialize_with = "deserialize_hashmap_string_or_vec")]
pub named_patterns: HashMap<String, Vec<String>>,
}
pub type VendorPatterns = Vec<String>;