cargolifter_core/models/
publish.rs

1use serde::{Deserialize, Serialize};
2use sha2::{Digest, Sha256};
3use std::collections::HashMap;
4use std::hash::Hash;
5
6#[derive(Clone, Debug, Default, Deserialize)]
7pub struct Dependency {
8    pub name: String,
9    pub version_req: String,
10    pub features: Vec<String>,
11    pub optional: bool,
12    pub default_features: bool,
13    pub target: Option<String>,
14    pub kind: String,
15    pub registry: Option<String>,
16    pub package: Option<String>,
17}
18
19#[derive(Clone, Debug, Default, Deserialize)]
20pub struct MetaData {
21    pub name: String,
22    pub vers: String,
23    pub deps: Vec<Dependency>,
24    pub features: HashMap<String, Vec<String>>,
25    pub authors: Vec<String>,
26    pub description: Option<String>,
27    pub documentation: Option<String>,
28    pub homepage: Option<String>,
29    pub readme: Option<String>,
30    pub readme_file: Option<String>,
31    pub keywords: Vec<String>,
32    pub categories: Vec<String>,
33    pub license: Option<String>,
34    pub license_file: Option<String>,
35    pub repository: Option<String>,
36    pub badges: HashMap<String, HashMap<String, String>>,
37    pub links: Option<String>,
38}
39
40#[derive(Debug, Default)]
41pub struct PublishRequest {
42    pub meta: MetaData,
43    pub data: Vec<u8>,
44}
45
46impl MetaData {
47    pub fn crate_file_path(&self) -> String {
48        crate::get_crate_file_path(&self.name)
49    }
50}
51
52#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
53pub struct PublishedDependency {
54    pub name: String,
55    pub req: String,
56    pub features: Vec<String>,
57    pub optional: bool,
58    pub default_features: bool,
59    pub target: Option<String>,
60    pub kind: String,
61    pub registry: Option<String>,
62    pub package: Option<String>,
63}
64
65impl std::convert::From<Dependency> for PublishedDependency {
66    fn from(dep: Dependency) -> Self {
67        Self {
68            name: dep.name,
69            req: dep.version_req,
70            features: dep.features,
71            optional: dep.optional,
72            default_features: dep.default_features,
73            target: dep.target,
74            kind: dep.kind,
75            registry: dep.registry,
76            package: dep.package,
77        }
78    }
79}
80
81#[derive(Debug, Serialize, Deserialize, Eq)]
82pub struct PublishedVersion {
83    pub name: String,
84    pub vers: String,
85    pub deps: Vec<PublishedDependency>,
86    pub cksum: String,
87    pub features: HashMap<String, Vec<String>>,
88    pub yanked: bool,
89    pub links: Option<String>,
90}
91
92impl std::convert::From<&PublishRequest> for PublishedVersion {
93    fn from(req: &PublishRequest) -> Self {
94        let cksum = Sha256::digest(&req.data);
95
96        Self {
97            name: req.meta.name.clone(),
98            vers: req.meta.vers.clone(),
99            deps: req
100                .meta
101                .deps
102                .clone()
103                .into_iter()
104                .map(|dep| dep.into())
105                .collect(),
106            cksum: hex::encode(cksum),
107            features: req.meta.features.clone(),
108            yanked: false,
109            links: req.meta.links.clone(),
110        }
111    }
112}
113
114impl std::cmp::PartialEq for PublishedVersion {
115    fn eq(&self, other: &Self) -> bool {
116        self.vers == other.vers && self.name == other.name
117    }
118}
119
120impl Hash for PublishedVersion {
121    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
122        self.name.hash(state);
123        self.vers.hash(state);
124    }
125}
126
127#[cfg(test)]
128mod tests {
129    #[test]
130    fn test_crate_file_path_1() {
131        let meta = super::MetaData {
132            name: "A".into(),
133            ..Default::default()
134        };
135        assert_eq!("1/A", meta.crate_file_path());
136    }
137
138    #[test]
139    fn test_crate_file_path_2() {
140        let meta = super::MetaData {
141            name: "AB".into(),
142            ..Default::default()
143        };
144        assert_eq!("2/AB", meta.crate_file_path());
145    }
146
147    #[test]
148    fn test_crate_file_path_3() {
149        let meta = super::MetaData {
150            name: "ABC".into(),
151            ..Default::default()
152        };
153        assert_eq!("3/A/ABC", meta.crate_file_path());
154    }
155
156    #[test]
157    fn test_crate_file_path_more() {
158        let meta = super::MetaData {
159            name: "ABCDE".into(),
160            ..Default::default()
161        };
162        assert_eq!("AB/CD/ABCDE", meta.crate_file_path());
163    }
164}