use std::fmt::{Display, Formatter};
use std::ops::Deref;
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Name {
value: String,
}
impl Name {
pub(crate) fn new<S: Into<String>>(full: S) -> Self {
Self { value: full.into() }
}
pub(crate) fn name(&self) -> &str {
match self.find() {
None => self.value.as_str(),
Some(pos) => {
let s = self.value.as_str();
if pos == s.len() - 1 {
""
} else {
&s[pos + 1..]
}
}
}
}
pub(crate) fn prefix(&self) -> Option<&str> {
match self.find() {
None => None,
Some(pos) => {
let s = self.value.as_str();
Some(&s[..pos])
}
}
}
pub(crate) fn full(&self) -> &str {
self.value.as_str()
}
pub(crate) fn set_name<S: AsRef<str>>(&mut self, name: S) {
match self.prefix() {
None => self.value = name.as_ref().into(),
Some(prefix) => {
let mut value = String::with_capacity(prefix.len() + 1 + name.as_ref().len());
value.push_str(prefix);
value.push(':');
value.push_str(name.as_ref());
self.value = value;
}
}
}
pub(crate) fn set_prefix<S: AsRef<str>>(&mut self, prefix: S) {
let name = self.name();
let mut value = String::with_capacity(prefix.as_ref().len() + 1 + name.len());
value.push_str(prefix.as_ref());
value.push(':');
value.push_str(name.as_ref());
self.value = value;
}
pub(crate) fn set_full<S: Into<String>>(&mut self, full: S) {
self.value = full.into();
}
}
impl Display for Name {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.full())
}
}
impl AsRef<str> for Name {
fn as_ref(&self) -> &str {
self.full().as_ref()
}
}
impl AsRef<String> for Name {
fn as_ref(&self) -> &String {
&self.value
}
}
impl From<Name> for String {
fn from(n: Name) -> Self {
n.value
}
}
impl From<&str> for Name {
fn from(s: &str) -> Self {
Name::new(s)
}
}
impl Deref for Name {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl From<String> for Name {
fn from(value: String) -> Self {
Self { value }
}
}
impl Name {
fn find(&self) -> Option<usize> {
self.value.as_str().find(':')
}
}
#[test]
fn ns_foo() {
let name = Name::new("ns:foo");
assert_eq!("ns", name.prefix().unwrap());
assert_eq!("foo", name.name());
assert_eq!("ns:foo", name.full());
}
#[test]
fn no_prefix() {
let name = Name::new("nsfoo");
assert!(name.prefix().is_none());
assert_eq!("nsfoo", name.name());
assert_eq!("nsfoo", name.full());
}
#[test]
fn weird_colons() {
let name = Name::new(":ns:foo:");
assert_eq!("", name.prefix().unwrap());
assert_eq!("ns:foo:", name.name());
assert_eq!(":ns:foo:", name.full());
}
#[test]
fn no_name_test() {
let name = Name::new("foo:");
assert_eq!("foo", name.prefix().unwrap());
assert_eq!("", name.name());
assert_eq!("foo:", name.full());
}
#[test]
fn set_prefix() {
let mut name = Name::new("xyz:bones");
name.set_prefix("cat");
assert_eq!("cat", name.prefix().unwrap());
assert_eq!("bones", name.name());
assert_eq!("cat:bones", name.full());
}
#[test]
fn set_name_test() {
let mut name = Name::new("xyz:bones");
name.set_name("bishop");
assert_eq!("xyz", name.prefix().unwrap());
assert_eq!("bishop", name.name());
assert_eq!("xyz:bishop", name.full());
}
#[test]
fn set_full_test() {
let mut name = Name::new("xyz:bones");
name.set_full("cat:bishop");
assert_eq!("cat", name.prefix().unwrap());
assert_eq!("bishop", name.name());
assert_eq!("cat:bishop", name.full());
}
#[test]
fn find_test() {
assert!(Name::new("xyz").find().is_none());
assert!(Name::new("").find().is_none());
assert_eq!(0, Name::new(":xyz").find().unwrap());
assert_eq!(0, Name::new(":x:yz").find().unwrap());
assert_eq!(1, Name::new("x:yz").find().unwrap());
assert_eq!(3, Name::new("xyz:").find().unwrap());
assert_eq!(0, Name::new(":").find().unwrap());
}