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