use std::{
borrow::Cow,
fmt::{self, Display},
ops::Deref,
};
use super::RefStr;
use crate::lit;
pub type Iter<'a> = std::str::Split<'a, char>;
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct Components<'a> {
inner: std::str::Split<'a, char>,
}
impl<'a> Iterator for Components<'a> {
type Item = Component<'a>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner
.next()
.map(RefStr::from_str)
.map(Cow::from)
.map(Component)
}
}
impl<'a> DoubleEndedIterator for Components<'a> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.inner
.next_back()
.map(RefStr::from_str)
.map(Cow::from)
.map(Component)
}
}
impl<'a> From<&'a RefStr> for Components<'a> {
#[inline]
fn from(rs: &'a RefStr) -> Self {
Self {
inner: rs.as_str().split('/'),
}
}
}
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
pub struct Component<'a>(Cow<'a, RefStr>);
impl<'a> Component<'a> {
#[inline]
pub fn from_refstr(r: impl Into<Cow<'a, RefStr>>) -> Option<Self> {
let r = r.into();
if !r.contains('/') {
Some(Self(r))
} else {
None
}
}
#[inline]
pub fn as_lit<T: lit::Lit>(&self) -> Option<T> {
T::from_component(self)
}
#[inline]
pub fn into_inner(self) -> Cow<'a, RefStr> {
self.0
}
}
impl<'a> Deref for Component<'a> {
type Target = RefStr;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<RefStr> for Component<'_> {
#[inline]
fn as_ref(&self) -> &RefStr {
self
}
}
impl<'a> From<&'a RefStr> for Option<Component<'a>> {
#[inline]
fn from(r: &'a RefStr) -> Self {
if !r.contains('/') {
Some(Component(Cow::from(r)))
} else {
None
}
}
}
impl<'a> From<Component<'a>> for Cow<'a, RefStr> {
#[inline]
fn from(c: Component<'a>) -> Self {
c.0
}
}
impl<T: lit::Lit> From<T> for Component<'static> {
#[inline]
fn from(_: T) -> Self {
Component(Cow::from(T::NAME))
}
}
impl<'a> From<lit::SomeLit<'a>> for Component<'a> {
#[inline]
fn from(s: lit::SomeLit<'a>) -> Self {
use lit::SomeLit::*;
match s {
Known(k) => k.into(),
Any(c) => c,
}
}
}
impl Display for Component<'_> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.0.as_str())
}
}
pub mod component {
use super::Component;
use crate::name;
use std::borrow::Cow;
pub const HEADS: Component = Component(Cow::Borrowed(name::HEADS));
pub const MAIN: Component = Component(Cow::Borrowed(name::MAIN));
pub const MASTER: Component = Component(Cow::Borrowed(name::MASTER));
pub const NAMESPACES: Component = Component(Cow::Borrowed(name::NAMESPACES));
pub const NOTES: Component = Component(Cow::Borrowed(name::NOTES));
pub const ORIGIN: Component = Component(Cow::Borrowed(name::ORIGIN));
pub const REFS: Component = Component(Cow::Borrowed(name::REFS));
pub const REMOTES: Component = Component(Cow::Borrowed(name::REMOTES));
pub const TAGS: Component = Component(Cow::Borrowed(name::TAGS));
}