1use crate::{name, Qualified, RefStr};
7
8pub trait Lit: Sized + sealed::Sealed {
19 const SELF: Self;
20 const NAME: &'static RefStr;
21
22 #[inline]
23 fn from_component(c: &name::Component) -> Option<Self> {
24 (c.as_ref() == Self::NAME).then_some(Self::SELF)
25 }
26}
27
28impl<T: Lit> From<T> for &'static RefStr {
29 #[inline]
30 fn from(_: T) -> Self {
31 T::NAME
32 }
33}
34
35mod sealed {
36 pub trait Sealed {}
37}
38
39#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
41pub enum KnownLit {
42 Refs,
43 Heads,
44 Namespaces,
45 Remotes,
46 Tags,
47 Notes,
48}
49
50impl KnownLit {
51 #[inline]
52 pub fn from_component(c: &name::Component) -> Option<Self> {
53 let c: &RefStr = c.as_ref();
54 if c == Refs::NAME {
55 Some(Self::Refs)
56 } else if c == Heads::NAME {
57 Some(Self::Heads)
58 } else if c == Namespaces::NAME {
59 Some(Self::Namespaces)
60 } else if c == Remotes::NAME {
61 Some(Self::Remotes)
62 } else if c == Tags::NAME {
63 Some(Self::Tags)
64 } else if c == Notes::NAME {
65 Some(Self::Notes)
66 } else {
67 None
68 }
69 }
70}
71
72impl From<KnownLit> for name::Component<'_> {
73 #[inline]
74 fn from(k: KnownLit) -> Self {
75 match k {
76 KnownLit::Refs => Refs.into(),
77 KnownLit::Heads => Heads.into(),
78 KnownLit::Namespaces => Namespaces.into(),
79 KnownLit::Remotes => Remotes.into(),
80 KnownLit::Tags => Tags.into(),
81 KnownLit::Notes => Notes.into(),
82 }
83 }
84}
85
86pub enum SomeLit<'a> {
88 Known(KnownLit),
89 Any(name::Component<'a>),
90}
91
92impl SomeLit<'_> {
93 pub fn known(self) -> Option<KnownLit> {
94 match self {
95 Self::Known(k) => Some(k),
96 _ => None,
97 }
98 }
99}
100
101impl<'a> From<name::Component<'a>> for SomeLit<'a> {
102 #[inline]
103 fn from(c: name::Component<'a>) -> Self {
104 match KnownLit::from_component(&c) {
105 Some(k) => Self::Known(k),
106 None => Self::Any(c),
107 }
108 }
109}
110
111pub type RefsHeads<T> = (Refs, Heads, T);
112pub type RefsTags<T> = (Refs, Tags, T);
113pub type RefsNotes<T> = (Refs, Notes, T);
114pub type RefsRemotes<T> = (Refs, Remotes, T);
115pub type RefsNamespaces<'a, T> = (Refs, Namespaces, T, Qualified<'a>);
116
117#[inline]
118pub fn refs_heads<T: AsRef<RefStr>>(name: T) -> RefsHeads<T> {
119 (Refs, Heads, name)
120}
121
122#[inline]
123pub fn refs_tags<T: AsRef<RefStr>>(name: T) -> RefsTags<T> {
124 (Refs, Tags, name)
125}
126
127#[inline]
128pub fn refs_notes<T: AsRef<RefStr>>(name: T) -> RefsNotes<T> {
129 (Refs, Notes, name)
130}
131
132#[inline]
133pub fn refs_remotes<T: AsRef<RefStr>>(name: T) -> RefsRemotes<T> {
134 (Refs, Remotes, name)
135}
136
137#[inline]
138pub fn refs_namespaces<'a, 'b, T>(namespace: T, name: Qualified<'b>) -> RefsNamespaces<'b, T>
139where
140 T: Into<name::Component<'a>>,
141{
142 (Refs, Namespaces, namespace, name)
143}
144
145#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
146pub struct Refs;
147
148impl Lit for Refs {
149 const SELF: Self = Self;
150 const NAME: &'static RefStr = name::REFS;
151}
152impl sealed::Sealed for Refs {}
153
154#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
155pub struct Heads;
156
157impl Lit for Heads {
158 const SELF: Self = Self;
159 const NAME: &'static RefStr = name::HEADS;
160}
161impl sealed::Sealed for Heads {}
162
163#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
164pub struct Namespaces;
165
166impl Lit for Namespaces {
167 const SELF: Self = Self;
168 const NAME: &'static RefStr = name::NAMESPACES;
169}
170impl sealed::Sealed for Namespaces {}
171
172#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
173pub struct Remotes;
174
175impl Lit for Remotes {
176 const SELF: Self = Self;
177 const NAME: &'static RefStr = name::REMOTES;
178}
179impl sealed::Sealed for Remotes {}
180
181#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
182pub struct Tags;
183
184impl Lit for Tags {
185 const SELF: Self = Self;
186 const NAME: &'static RefStr = name::TAGS;
187}
188impl sealed::Sealed for Tags {}
189
190#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
191pub struct Notes;
192
193impl Lit for Notes {
194 const SELF: Self = Self;
195 const NAME: &'static RefStr = name::NOTES;
196}
197impl sealed::Sealed for Notes {}