use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RegistryRef {
pub id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub uri: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum RegistryPublicationStatus {
Draft,
Experimental,
Standard,
Deprecated,
Obsolete,
}
impl RegistryPublicationStatus {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Self::Draft => "draft",
Self::Experimental => "experimental",
Self::Standard => "standard",
Self::Deprecated => "deprecated",
Self::Obsolete => "obsolete",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum RegistryEntryStatus {
Draft,
Experimental,
Standard,
Deprecated,
Obsolete,
}
impl RegistryEntryStatus {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Self::Draft => "draft",
Self::Experimental => "experimental",
Self::Standard => "standard",
Self::Deprecated => "deprecated",
Self::Obsolete => "obsolete",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum RegistryCategory {
SemanticAction,
Function,
Rule,
LogicalType,
Diagnostic,
ExtensionNamespace,
Profile,
Capability,
}
impl RegistryCategory {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Self::SemanticAction => "semanticAction",
Self::Function => "function",
Self::Rule => "rule",
Self::LogicalType => "logicalType",
Self::Diagnostic => "diagnostic",
Self::ExtensionNamespace => "extensionNamespace",
Self::Profile => "profile",
Self::Capability => "capability",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ExtensionCompatibility {
Mandatory,
Optional,
}
impl ExtensionCompatibility {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Self::Mandatory => "mandatory",
Self::Optional => "optional",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RegistryEntry {
#[serde(default)]
pub id: String,
pub name: String,
pub category: RegistryCategory,
pub version: String,
pub status: RegistryEntryStatus,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub compatibility: Option<ExtensionCompatibility>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub definition: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub references: Vec<String>,
#[serde(default = "default_supported")]
pub supported: bool,
}
fn default_supported() -> bool {
true
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RegistryDocument {
pub id: String,
pub version: String,
pub governing_specification: String,
pub publication_status: RegistryPublicationStatus,
#[serde(default)]
pub entries: IndexMap<String, RegistryEntry>,
}
impl RegistryDocument {
#[must_use]
pub fn get(&self, id: &str) -> Option<&RegistryEntry> {
self.entries.get(id)
}
pub fn insert(&mut self, entry: RegistryEntry) {
self.entries.insert(entry.id.clone(), entry);
}
pub fn merge(&mut self, other: &RegistryDocument) {
for (id, entry) in &other.entries {
if id.starts_with("dtcs:") && self.entries.contains_key(id) {
continue;
}
self.entries.insert(id.clone(), entry.clone());
}
}
#[must_use]
pub fn list(&self) -> Vec<&RegistryEntry> {
self.entries.values().collect()
}
}