use std::num::Wrapping;
use crate::dtype::DataType;
use wikidata::{Fid, Lid, Pid, Qid, Sid};
pub enum Id {
Fid(Fid),
Lid(Lid),
Pid(Pid),
Qid(Qid),
Sid(Sid),
DataType(DataType),
}
impl<'a> From<&'a str> for Id {
fn from(value: &'a str) -> Self {
match value.get(0..1) {
Some("L") => Self::Lid(Lid(value[1..].parse::<u64>().unwrap())),
Some("P") => Self::Pid(Pid(value[1..].parse::<u64>().unwrap())),
Some("Q") => Self::Qid(Qid(value[1..].parse::<u64>().unwrap())),
Some("F") => {
let mut parts = value[1..].split('-');
Self::Fid(Fid(
Lid(parts.next().unwrap().parse::<u64>().unwrap()),
parts.next().unwrap()[1..].parse::<u16>().unwrap(),
))
}
Some("S") => {
let mut parts = value[1..].split('-');
Self::Sid(Sid(
Lid(parts.next().unwrap().parse::<u64>().unwrap()),
parts.next().unwrap()[1..].parse::<u16>().unwrap(),
))
}
Some("@") => match &value[1..] {
"Quantity" => Self::DataType(DataType::Quantity),
"Coordinate" => Self::DataType(DataType::Coordinate),
"String" => Self::DataType(DataType::String),
"DateTime" => Self::DataType(DataType::DateTime),
"Entity" => Self::DataType(DataType::Entity),
&_ => panic!("Unknown data type: {}", value),
},
_ => panic!("Not valid value: {}", value),
}
}
}
impl From<Id> for u32 {
fn from(id: Id) -> Self {
match id {
Id::Fid(fid) => {
(Wrapping(u32::from(Id::Lid(fid.0))) + Wrapping(fid.1 as u32 + 3_000_000_000)).0
}
Id::Lid(lid) => lid.0 as u32 + 2_000_000_000,
Id::Pid(pid) => pid.0 as u32 + 1_000_000_000,
Id::Qid(qid) => qid.0 as u32,
Id::Sid(sid) => {
(Wrapping(u32::from(Id::Lid(sid.0)))
+ Wrapping(sid.1 as u32 + 3_000_000_000)
+ Wrapping(500_000_000))
.0
}
Id::DataType(dt) => u8::from(&dt) as u32 + 4_000_000_000,
}
}
}