use serde::{Deserialize, Serialize};
use std::fmt;
pub const LSG_VERSION: u16 = 1;
pub const LSG_VERSION_LABEL: &str = "LSG/1";
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct GrammarEpoch {
pub number: u16,
}
impl GrammarEpoch {
pub const E0001: Self = Self { number: 1 };
pub fn label(&self) -> String {
format!("LSG/{}-E{:04}", LSG_VERSION, self.number)
}
pub fn parse(s: &str) -> Option<Self> {
let s = s.trim();
let epoch_part = if let Some(rest) = s.strip_prefix("LSG/") {
let mut parts = rest.split('-');
let ver = parts.next()?;
if ver != "1" && ver != LSG_VERSION.to_string() {
if ver.parse::<u16>().ok()? != LSG_VERSION {
return None;
}
}
parts.next()?
} else {
s
};
let num = epoch_part
.strip_prefix('E')
.or_else(|| epoch_part.strip_prefix('e'))?;
let number = num.parse().ok()?;
Some(Self { number })
}
}
impl fmt::Display for GrammarEpoch {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.label())
}
}
impl Default for GrammarEpoch {
fn default() -> Self {
Self::E0001
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ReaderCompatibility {
pub reader_id: String,
pub supported_epochs: Vec<GrammarEpoch>,
}
impl ReaderCompatibility {
pub fn supports(&self, epoch: &GrammarEpoch) -> bool {
self.supported_epochs.iter().any(|e| e == epoch)
}
}