cargo_util_schemas/core/
source_kind.rs
1use std::cmp::Ordering;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum SourceKind {
6 Git(GitReference),
8 Path,
10 Registry,
12 SparseRegistry,
14 LocalRegistry,
16 Directory,
18}
19
20impl std::hash::Hash for SourceKind {
25 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
26 core::mem::discriminant(self).hash(state);
27 if let SourceKind::Git(git) = self {
28 git.hash(state);
29 }
30 }
31}
32
33impl SourceKind {
34 pub fn protocol(&self) -> Option<&str> {
35 match self {
36 SourceKind::Path => Some("path"),
37 SourceKind::Git(_) => Some("git"),
38 SourceKind::Registry => Some("registry"),
39 SourceKind::SparseRegistry => None,
41 SourceKind::LocalRegistry => Some("local-registry"),
42 SourceKind::Directory => Some("directory"),
43 }
44 }
45}
46
47impl Ord for SourceKind {
51 fn cmp(&self, other: &SourceKind) -> Ordering {
52 match (self, other) {
53 (SourceKind::Path, SourceKind::Path) => Ordering::Equal,
54 (SourceKind::Path, _) => Ordering::Less,
55 (_, SourceKind::Path) => Ordering::Greater,
56
57 (SourceKind::Registry, SourceKind::Registry) => Ordering::Equal,
58 (SourceKind::Registry, _) => Ordering::Less,
59 (_, SourceKind::Registry) => Ordering::Greater,
60
61 (SourceKind::SparseRegistry, SourceKind::SparseRegistry) => Ordering::Equal,
62 (SourceKind::SparseRegistry, _) => Ordering::Less,
63 (_, SourceKind::SparseRegistry) => Ordering::Greater,
64
65 (SourceKind::LocalRegistry, SourceKind::LocalRegistry) => Ordering::Equal,
66 (SourceKind::LocalRegistry, _) => Ordering::Less,
67 (_, SourceKind::LocalRegistry) => Ordering::Greater,
68
69 (SourceKind::Directory, SourceKind::Directory) => Ordering::Equal,
70 (SourceKind::Directory, _) => Ordering::Less,
71 (_, SourceKind::Directory) => Ordering::Greater,
72
73 (SourceKind::Git(a), SourceKind::Git(b)) => a.cmp(b),
74 }
75 }
76}
77
78impl PartialOrd for SourceKind {
80 fn partial_cmp(&self, other: &SourceKind) -> Option<Ordering> {
81 Some(self.cmp(other))
82 }
83}
84
85#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
87pub enum GitReference {
88 Tag(String),
90 Branch(String),
92 Rev(String),
95 DefaultBranch,
97}
98
99impl GitReference {
100 pub fn from_query(
101 query_pairs: impl Iterator<Item = (impl AsRef<str>, impl AsRef<str>)>,
102 ) -> Self {
103 let mut reference = GitReference::DefaultBranch;
104 for (k, v) in query_pairs {
105 let v = v.as_ref();
106 match k.as_ref() {
107 "branch" | "ref" => reference = GitReference::Branch(v.to_owned()),
109
110 "rev" => reference = GitReference::Rev(v.to_owned()),
111 "tag" => reference = GitReference::Tag(v.to_owned()),
112 _ => {}
113 }
114 }
115 reference
116 }
117
118 pub fn pretty_ref(&self, url_encoded: bool) -> Option<PrettyRef<'_>> {
121 match self {
122 GitReference::DefaultBranch => None,
123 _ => Some(PrettyRef {
124 inner: self,
125 url_encoded,
126 }),
127 }
128 }
129}
130
131pub struct PrettyRef<'a> {
133 inner: &'a GitReference,
134 url_encoded: bool,
135}
136
137impl<'a> std::fmt::Display for PrettyRef<'a> {
138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 let value: &str;
140 match self.inner {
141 GitReference::Branch(s) => {
142 write!(f, "branch=")?;
143 value = s;
144 }
145 GitReference::Tag(s) => {
146 write!(f, "tag=")?;
147 value = s;
148 }
149 GitReference::Rev(s) => {
150 write!(f, "rev=")?;
151 value = s;
152 }
153 GitReference::DefaultBranch => unreachable!(),
154 }
155 if self.url_encoded {
156 for value in url::form_urlencoded::byte_serialize(value.as_bytes()) {
157 write!(f, "{value}")?;
158 }
159 } else {
160 write!(f, "{value}")?;
161 }
162 Ok(())
163 }
164}