use std::hash::{Hash, Hasher};
#[derive(Clone, Debug)]
pub struct RelName {
key: String,
spelled: String,
dot: usize,
qualified: bool,
}
impl RelName {
pub fn new(schema: &str, name: &str) -> Result<Self, String> {
Self::build(schema, name, true)
}
pub fn unqualified(schema: &str, name: &str) -> Result<Self, String> {
Self::build(schema, name, false)
}
fn build(schema: &str, name: &str, qualified: bool) -> Result<Self, String> {
let schema_key = match schema.eq_ignore_ascii_case(gnitz_wire::LOCAL_SCHEMA) {
true => gnitz_wire::LOCAL_SCHEMA.to_string(),
false => gnitz_wire::canonical_identifier(schema)?,
};
let key = gnitz_wire::qualified_key(&schema_key, &gnitz_wire::canonical_identifier(name)?);
Ok(RelName {
key,
spelled: gnitz_wire::qualified_key(schema, name),
dot: schema.len(),
qualified,
})
}
pub fn parse(default_schema: &str, text: &str) -> Result<Self, String> {
match text.split_once('.') {
Some((schema, name)) => Self::new(schema, name),
None => Self::unqualified(default_schema, text),
}
}
pub fn is_qualified(&self) -> bool {
self.qualified
}
pub fn schema(&self) -> &str {
&self.key[..self.dot]
}
pub fn name(&self) -> &str {
&self.key[self.dot + 1..]
}
pub fn key(&self) -> &str {
&self.key
}
pub fn spelled_name(&self) -> &str {
&self.spelled[self.dot + 1..]
}
pub fn sibling(&self, name: &str) -> Result<Self, String> {
Self::build(&self.spelled[..self.dot], name, self.qualified)
}
}
impl PartialEq for RelName {
fn eq(&self, other: &Self) -> bool {
self.key == other.key
}
}
impl Eq for RelName {}
impl Hash for RelName {
fn hash<H: Hasher>(&self, state: &mut H) {
self.key.hash(state);
}
}
impl std::fmt::Display for RelName {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self.qualified {
true => &self.spelled,
false => self.spelled_name(),
})
}
}
#[cfg(test)]
#[path = "tests/rel_name.rs"]
mod tests;