radicle_git_ref_format/refspec/
iter.rs1use std::fmt::{self, Display};
2
3use super::PatternStr;
4use crate::{RefStr, lit};
5
6pub type Iter<'a> = std::str::Split<'a, char>;
7
8pub enum Component<'a> {
9 Glob(Option<&'a PatternStr>),
10 Normal(&'a RefStr),
11}
12
13impl Component<'_> {
14 #[inline]
15 pub fn as_str(&self) -> &str {
16 self.as_ref()
17 }
18}
19
20impl AsRef<str> for Component<'_> {
21 #[inline]
22 fn as_ref(&self) -> &str {
23 match self {
24 Self::Glob(None) => "*",
25 Self::Glob(Some(x)) => x.as_str(),
26 Self::Normal(x) => x.as_str(),
27 }
28 }
29}
30
31impl Display for Component<'_> {
32 #[inline]
33 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34 f.write_str(self.as_str())
35 }
36}
37
38impl<T: lit::Lit> From<T> for Component<'static> {
39 #[inline]
40 fn from(_: T) -> Self {
41 Self::Normal(T::NAME)
42 }
43}
44
45#[must_use = "iterators are lazy and do nothing unless consumed"]
46#[derive(Clone)]
47pub struct Components<'a> {
48 inner: Iter<'a>,
49}
50
51impl<'a> Iterator for Components<'a> {
52 type Item = Component<'a>;
53
54 #[inline]
55 fn next(&mut self) -> Option<Self::Item> {
56 self.inner.next().map(|next| match next {
57 "*" => Component::Glob(None),
58 x if x.contains('*') => Component::Glob(Some(PatternStr::from_str(x))),
59 x => Component::Normal(RefStr::from_str(x)),
60 })
61 }
62}
63
64impl DoubleEndedIterator for Components<'_> {
65 #[inline]
66 fn next_back(&mut self) -> Option<Self::Item> {
67 self.inner.next_back().map(|next| match next {
68 "*" => Component::Glob(None),
69 x if x.contains('*') => Component::Glob(Some(PatternStr::from_str(x))),
70 x => Component::Normal(RefStr::from_str(x)),
71 })
72 }
73}
74
75impl<'a> From<&'a PatternStr> for Components<'a> {
76 #[inline]
77 fn from(p: &'a PatternStr) -> Self {
78 Self {
79 inner: p.as_str().split('/'),
80 }
81 }
82}
83
84pub mod component {
85 use super::Component;
86 use crate::name;
87
88 pub const STAR: Component = Component::Glob(None);
89 pub const HEADS: Component = Component::Normal(name::HEADS);
90 pub const MAIN: Component = Component::Normal(name::MAIN);
91 pub const MASTER: Component = Component::Normal(name::MASTER);
92 pub const NAMESPACES: Component = Component::Normal(name::NAMESPACES);
93 pub const NOTES: Component = Component::Normal(name::NOTES);
94 pub const ORIGIN: Component = Component::Normal(name::ORIGIN);
95 pub const REFS: Component = Component::Normal(name::REFS);
96 pub const REMOTES: Component = Component::Normal(name::REMOTES);
97 pub const TAGS: Component = Component::Normal(name::TAGS);
98}