use std::fmt;
use substrate_data::{Id, Reader, Schema, Shape, Value, ValueRef};
use crate::kinds;
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Res {
pub set: String,
pub key: String,
}
impl Res {
pub fn name(&self) -> String {
format!("{}{}{}", self.set, yog_ids::sep::DOT, self.key)
}
pub fn parse(spelled: &str) -> Option<Res> {
let (set, key) = spelled.split_once(yog_ids::sep::DOT)?;
let set_ok = set.starts_with(|c: char| c.is_ascii_uppercase())
&& set.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'_');
(set_ok && is_key(key)).then(|| Res {
set: set.to_owned(),
key: key.to_owned(),
})
}
}
pub fn is_key(key: &str) -> bool {
key.starts_with(|c: char| c.is_ascii_alphabetic() || c == '_')
&& key.split(yog_ids::sep::DOT).all(|part| {
!part.is_empty() && part.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'_')
})
}
impl fmt::Display for Res {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}{}", yog_ids::reference::RES, self.name())
}
}
impl Schema for Res {
fn shape() -> Shape {
substrate_data::schema::ref_shape::<kinds::Res>()
}
fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<Self> {
let id = Id::<kinds::Res>::read(v, cx)?;
Res::parse(&id.id).or_else(|| {
cx.problem(format!(
"`{}`: an entry is `@res:Set.key` with an upper-case set (`@res:Strings.title`)",
id.id
));
None
})
}
fn write(&self) -> Value {
Id::<kinds::Res>::new(self.name()).write()
}
}