use std::borrow::Cow;
use std::fmt;
use crate::model::value::RefKey;
use crate::schema::{Expected, Schema};
pub trait RefId: Schema + Clone + PartialEq + fmt::Debug {
const EXPECTED: Expected;
fn parse(spelled: &str) -> Option<Self>;
fn spell(&self) -> Cow<'_, str>;
}
impl RefId for String {
const EXPECTED: Expected = Expected::Text;
fn parse(spelled: &str) -> Option<Self> {
RefKey::is_valid(spelled).then(|| spelled.to_owned())
}
fn spell(&self) -> Cow<'_, str> {
Cow::Borrowed(self)
}
}
macro_rules! number_ids {
($($t:ty => $what:ident),*) => {$(
impl RefId for $t {
const EXPECTED: Expected = Expected::$what;
fn parse(spelled: &str) -> Option<Self> {
let digits = spelled.strip_prefix('-').unwrap_or(spelled);
if digits.is_empty() || !digits.bytes().all(|b| b.is_ascii_digit()) {
return None;
}
spelled.parse().ok()
}
fn spell(&self) -> Cow<'_, str> {
Cow::Owned(self.to_string())
}
}
)*};
}
number_ids!(u32 => Unsigned, u64 => Unsigned, i64 => Integer);