use std::fmt::{Display, Formatter};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MeaningId {
pub wikidata_item: Option<String>,
pub wikidata_sense: Option<String>,
pub wiktionary_page: Option<String>,
}
impl MeaningId {
#[must_use]
#[allow(dead_code)]
pub fn from_item(item: impl Into<String>) -> Self {
Self {
wikidata_item: Some(item.into()),
wikidata_sense: None,
wiktionary_page: None,
}
}
#[must_use]
pub fn from_sense(sense: impl Into<String>) -> Self {
Self {
wikidata_item: None,
wikidata_sense: Some(sense.into()),
wiktionary_page: None,
}
}
#[must_use]
pub fn from_wiktionary_page(lang: &str, title: &str) -> Self {
Self {
wikidata_item: None,
wikidata_sense: None,
wiktionary_page: Some(format!("{lang}:{title}")),
}
}
#[must_use]
pub fn slug(&self) -> String {
if let Some(item) = self.wikidata_item.as_deref() {
return format!("wikidata:{item}");
}
if let Some(sense) = self.wikidata_sense.as_deref() {
return format!("wikidata-sense:{sense}");
}
if let Some(page) = self.wiktionary_page.as_deref() {
return format!("wiktionary:{page}");
}
String::from("meaning:unknown")
}
#[must_use]
#[allow(dead_code)]
pub const fn is_wikidata_backed(&self) -> bool {
self.wikidata_item.is_some() || self.wikidata_sense.is_some()
}
}
impl Display for MeaningId {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
formatter.write_str(&self.slug())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn slug_prefers_q_item_then_sense_then_wiktionary() {
assert_eq!(MeaningId::from_item("Q42").slug(), "wikidata:Q42");
assert_eq!(
MeaningId::from_sense("L8485-S1").slug(),
"wikidata-sense:L8485-S1"
);
assert_eq!(
MeaningId::from_wiktionary_page("en", "hello").slug(),
"wiktionary:en:hello"
);
}
#[test]
fn equal_ids_carry_the_same_wikidata_pointer() {
let a = MeaningId::from_item("Q1369");
let b = MeaningId::from_item("Q1369");
assert_eq!(a, b);
let c = MeaningId::from_sense("L1-S1");
assert_ne!(a, c);
}
#[test]
fn wikidata_backed_predicate_distinguishes_fallback_from_item() {
assert!(MeaningId::from_item("Q42").is_wikidata_backed());
assert!(MeaningId::from_sense("L1-S1").is_wikidata_backed());
assert!(!MeaningId::from_wiktionary_page("en", "x").is_wikidata_backed());
}
}