#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize)]
#[non_exhaustive]
pub enum MappingProvenance {
#[serde(rename = "actual_text")]
ActualText,
#[serde(rename = "to_unicode")]
ToUnicode,
#[serde(rename = "encoding")]
EncodingName,
#[serde(rename = "predefined_cmap")]
PredefinedCMap,
#[serde(rename = "embedded_cmap")]
EmbeddedCmap,
#[serde(rename = "fallback")]
Fallback,
}
impl MappingProvenance {
#[must_use]
pub fn rank(self) -> u8 {
match self {
Self::ActualText => 0,
Self::ToUnicode => 1,
Self::EncodingName => 2,
Self::PredefinedCMap => 3,
Self::EmbeddedCmap => 4,
Self::Fallback => 5,
}
}
#[must_use]
pub fn is_from_file(self) -> bool {
!matches!(self, Self::Fallback)
}
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Self::ActualText => "actual_text",
Self::ToUnicode => "to_unicode",
Self::EncodingName => "encoding",
Self::PredefinedCMap => "predefined_cmap",
Self::EmbeddedCmap => "embedded_cmap",
Self::Fallback => "fallback",
}
}
#[must_use]
pub fn weaker(self, other: Self) -> Self {
if self.rank() >= other.rank() {
self
} else {
other
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rank_orders_most_to_least_authoritative() {
let ordered = [
MappingProvenance::ActualText,
MappingProvenance::ToUnicode,
MappingProvenance::EncodingName,
MappingProvenance::PredefinedCMap,
MappingProvenance::EmbeddedCmap,
MappingProvenance::Fallback,
];
for pair in ordered.windows(2) {
assert!(pair[0].rank() < pair[1].rank(), "{:?} must outrank {:?}", pair[0], pair[1]);
}
}
#[test]
fn only_fallback_is_not_from_file() {
assert!(!MappingProvenance::Fallback.is_from_file());
for p in [
MappingProvenance::ActualText,
MappingProvenance::ToUnicode,
MappingProvenance::EncodingName,
MappingProvenance::PredefinedCMap,
MappingProvenance::EmbeddedCmap,
] {
assert!(p.is_from_file(), "{p:?} is a real mapping tier");
}
}
#[test]
fn weaker_summarises_a_run_by_its_least_trustworthy_char() {
let span = MappingProvenance::ToUnicode
.weaker(MappingProvenance::ToUnicode)
.weaker(MappingProvenance::Fallback);
assert_eq!(span, MappingProvenance::Fallback);
let clean = MappingProvenance::ToUnicode.weaker(MappingProvenance::ActualText);
assert_eq!(clean, MappingProvenance::ToUnicode);
}
}