1use std::collections::BTreeSet;
5use std::fmt;
6
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
11pub struct CrateId {
12 pub name: String,
14 pub version: semver::Version,
16}
17
18impl fmt::Display for CrateId {
19 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20 write!(f, "{}@{}", self.name, self.version)
21 }
22}
23
24#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
29pub struct FeatureSet(pub BTreeSet<String>);
30
31impl FeatureSet {
32 #[must_use]
34 pub const fn new() -> Self {
35 Self(BTreeSet::new())
36 }
37
38 #[must_use]
40 pub fn is_empty(&self) -> bool {
41 self.0.is_empty()
42 }
43
44 #[must_use]
47 pub fn short_hash(&self) -> String {
48 let mut hasher = blake3::Hasher::new();
49 for f in &self.0 {
50 hasher.update(f.as_bytes());
51 }
52 hex::encode(&hasher.finalize().as_bytes()[..4])
53 }
54}
55
56impl Default for FeatureSet {
57 fn default() -> Self {
58 Self::new()
59 }
60}
61
62impl FromIterator<String> for FeatureSet {
63 fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> Self {
64 Self(iter.into_iter().collect())
65 }
66}