1
+ use std:: collections:: BTreeMap ;
2
+ use std:: fmt;
3
+ use std:: { cmp:: Ordering , str:: FromStr } ;
4
+
5
+ use serde:: { Deserialize , Serialize , de, ser} ;
6
+ use url:: Url ;
7
+
8
+ use crate :: core:: { GitReference , SourceKind } ;
9
+
10
+ /// The `Cargo.lock` structure.
11
+ #[ derive( Serialize , Deserialize , Debug ) ]
12
+ pub struct EncodableResolve {
13
+ pub version : Option < u32 > ,
14
+ pub package : Option < Vec < EncodableDependency > > ,
15
+ /// `root` is optional to allow backward compatibility.
16
+ pub root : Option < EncodableDependency > ,
17
+ pub metadata : Option < Metadata > ,
18
+ #[ serde( default , skip_serializing_if = "Patch::is_empty" ) ]
19
+ pub patch : Patch ,
20
+ }
21
+
22
+ #[ derive( Serialize , Deserialize , Debug , Default ) ]
23
+ pub struct Patch {
24
+ pub unused : Vec < EncodableDependency > ,
25
+ }
26
+
27
+ pub type Metadata = BTreeMap < String , String > ;
28
+
29
+ impl Patch {
30
+ fn is_empty ( & self ) -> bool {
31
+ self . unused . is_empty ( )
32
+ }
33
+ }
34
+
35
+ #[ derive( Serialize , Deserialize , Debug , PartialOrd , Ord , PartialEq , Eq ) ]
36
+ pub struct EncodableDependency {
37
+ pub name : String ,
38
+ pub version : String ,
39
+ pub source : Option < EncodableSourceId > ,
40
+ pub checksum : Option < String > ,
41
+ pub dependencies : Option < Vec < EncodablePackageId > > ,
42
+ pub replace : Option < EncodablePackageId > ,
43
+ }
44
+
45
+ #[ derive( Debug , Clone ) ]
46
+ pub struct EncodableSourceId {
47
+ /// Full string of the source
48
+ source_str : String ,
49
+ /// Used for sources ordering
50
+ kind : SourceKind ,
51
+ /// Used for sources ordering
52
+ url : Url ,
53
+ }
54
+
55
+ impl EncodableSourceId {
56
+ pub fn new ( source : String ) -> Result < Self , EncodableSourceIdError > {
57
+ let source_str = source. clone ( ) ;
58
+ let ( kind, url) = source. split_once ( '+' ) . ok_or_else ( || {
59
+ EncodableSourceIdError ( EncodableSourceIdErrorKind :: InvalidSource ( source. clone ( ) ) . into ( ) )
60
+ } ) ?;
61
+
62
+ let url = Url :: parse ( url) . map_err ( |msg| EncodableSourceIdErrorKind :: InvalidUrl {
63
+ url : url. to_string ( ) ,
64
+ msg : msg. to_string ( ) ,
65
+ } ) ?;
66
+
67
+ let kind = match kind {
68
+ "git" => {
69
+ let reference = GitReference :: from_query ( url. query_pairs ( ) ) ;
70
+ SourceKind :: Git ( reference)
71
+ }
72
+ "registry" => SourceKind :: Registry ,
73
+ "sparse" => SourceKind :: SparseRegistry ,
74
+ "path" => SourceKind :: Path ,
75
+ kind => {
76
+ return Err ( EncodableSourceIdErrorKind :: UnsupportedSource ( kind. to_string ( ) ) . into ( ) ) ;
77
+ }
78
+ } ;
79
+
80
+ Ok ( Self {
81
+ source_str,
82
+ kind,
83
+ url,
84
+ } )
85
+ }
86
+
87
+ pub fn kind ( & self ) -> & SourceKind {
88
+ & self . kind
89
+ }
90
+
91
+ pub fn url ( & self ) -> & Url {
92
+ & self . url
93
+ }
94
+
95
+ pub fn source_str ( & self ) -> & String {
96
+ & self . source_str
97
+ }
98
+
99
+ pub fn as_url ( & self ) -> impl fmt:: Display + ' _ {
100
+ self . source_str . clone ( )
101
+ }
102
+ }
103
+
104
+ impl ser:: Serialize for EncodableSourceId {
105
+ fn serialize < S > ( & self , s : S ) -> Result < S :: Ok , S :: Error >
106
+ where
107
+ S : ser:: Serializer ,
108
+ {
109
+ s. collect_str ( & self . as_url ( ) )
110
+ }
111
+ }
112
+
113
+ impl < ' de > de:: Deserialize < ' de > for EncodableSourceId {
114
+ fn deserialize < D > ( d : D ) -> Result < Self , D :: Error >
115
+ where
116
+ D : de:: Deserializer < ' de > ,
117
+ {
118
+ let s = String :: deserialize ( d) ?;
119
+ Ok ( EncodableSourceId :: new ( s) . map_err ( de:: Error :: custom) ?)
120
+ }
121
+ }
122
+
123
+ impl std:: hash:: Hash for EncodableSourceId {
124
+ fn hash < H : std:: hash:: Hasher > ( & self , state : & mut H ) {
125
+ self . kind . hash ( state) ;
126
+ self . url . hash ( state) ;
127
+ }
128
+ }
129
+
130
+ impl std:: cmp:: PartialEq for EncodableSourceId {
131
+ fn eq ( & self , other : & Self ) -> bool {
132
+ self . kind == other. kind && self . url == other. url
133
+ }
134
+ }
135
+
136
+ impl std:: cmp:: Eq for EncodableSourceId { }
137
+
138
+ impl PartialOrd for EncodableSourceId {
139
+ fn partial_cmp ( & self , other : & EncodableSourceId ) -> Option < Ordering > {
140
+ Some ( self . cmp ( other) )
141
+ }
142
+ }
143
+
144
+ impl Ord for EncodableSourceId {
145
+ fn cmp ( & self , other : & EncodableSourceId ) -> Ordering {
146
+ self . kind
147
+ . cmp ( & other. kind )
148
+ . then_with ( || self . url . cmp ( & other. url ) )
149
+ }
150
+ }
151
+
152
+ #[ derive( Debug , PartialOrd , Ord , PartialEq , Eq , Hash , Clone ) ]
153
+ pub struct EncodablePackageId {
154
+ pub name : String ,
155
+ pub version : Option < String > ,
156
+ pub source : Option < EncodableSourceId > ,
157
+ }
158
+
159
+ impl fmt:: Display for EncodablePackageId {
160
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
161
+ write ! ( f, "{}" , self . name) ?;
162
+ if let Some ( s) = & self . version {
163
+ write ! ( f, " {}" , s) ?;
164
+ }
165
+ if let Some ( s) = & self . source {
166
+ write ! ( f, " ({})" , s. as_url( ) ) ?;
167
+ }
168
+ Ok ( ( ) )
169
+ }
170
+ }
171
+
172
+ impl FromStr for EncodablePackageId {
173
+ type Err = EncodablePackageIdError ;
174
+
175
+ fn from_str ( s : & str ) -> Result < EncodablePackageId , Self :: Err > {
176
+ let mut s = s. splitn ( 3 , ' ' ) ;
177
+ let name = s. next ( ) . unwrap ( ) ;
178
+ let version = s. next ( ) ;
179
+ let source_id = match s. next ( ) {
180
+ Some ( s) => {
181
+ if let Some ( s) = s. strip_prefix ( '(' ) . and_then ( |s| s. strip_suffix ( ')' ) ) {
182
+ Some ( EncodableSourceId :: new ( s. to_string ( ) ) ?)
183
+ } else {
184
+ return Err ( EncodablePackageIdErrorKind :: InvalidSerializedPackageId . into ( ) ) ;
185
+ }
186
+ }
187
+ None => None ,
188
+ } ;
189
+
190
+ Ok ( EncodablePackageId {
191
+ name : name. to_string ( ) ,
192
+ version : version. map ( |v| v. to_string ( ) ) ,
193
+ source : source_id,
194
+ } )
195
+ }
196
+ }
197
+
198
+ impl ser:: Serialize for EncodablePackageId {
199
+ fn serialize < S > ( & self , s : S ) -> Result < S :: Ok , S :: Error >
200
+ where
201
+ S : ser:: Serializer ,
202
+ {
203
+ s. collect_str ( self )
204
+ }
205
+ }
206
+
207
+ impl < ' de > de:: Deserialize < ' de > for EncodablePackageId {
208
+ fn deserialize < D > ( d : D ) -> Result < EncodablePackageId , D :: Error >
209
+ where
210
+ D : de:: Deserializer < ' de > ,
211
+ {
212
+ String :: deserialize ( d) . and_then ( |string| {
213
+ string
214
+ . parse :: < EncodablePackageId > ( )
215
+ . map_err ( de:: Error :: custom)
216
+ } )
217
+ }
218
+ }
219
+
1
220
#[ derive( Debug , thiserror:: Error ) ]
2
221
#[ error( transparent) ]
3
- pub struct EncodableSourceIdError ( #[ from] pub EncodableSourceIdErrorKind ) ;
222
+ pub struct EncodableSourceIdError ( #[ from] EncodableSourceIdErrorKind ) ;
4
223
5
224
#[ non_exhaustive]
6
225
#[ derive( Debug , thiserror:: Error ) ]
7
- pub enum EncodableSourceIdErrorKind {
226
+ enum EncodableSourceIdErrorKind {
8
227
#[ error( "invalid source `{0}`" ) ]
9
228
InvalidSource ( String ) ,
10
229
@@ -27,7 +246,7 @@ impl From<EncodableSourceIdError> for EncodablePackageIdError {
27
246
28
247
#[ non_exhaustive]
29
248
#[ derive( Debug , thiserror:: Error ) ]
30
- pub enum EncodablePackageIdErrorKind {
249
+ enum EncodablePackageIdErrorKind {
31
250
#[ error( "invalid serialied PackageId" ) ]
32
251
InvalidSerializedPackageId ,
33
252
0 commit comments