Skip to content

Commit 52db0c1

Browse files
committed
Auto merge of #5374 - matklad:simplify, r=alexcrichton
Simplify RegistryPackage deserialization Just mapping dependencies seems so much simpler than thread locals / deserializers with default. Am I missing something, or this indeed will work? :-) cc @Mark-Simulacrum
2 parents 30bf81b + 41e3861 commit 52db0c1

File tree

2 files changed

+56
-187
lines changed

2 files changed

+56
-187
lines changed

src/cargo/sources/registry/index.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ use std::collections::HashMap;
22
use std::path::Path;
33
use std::str;
44

5-
use serde::de::DeserializeSeed;
65
use serde_json;
76
use semver::Version;
87

98
use core::dependency::Dependency;
109
use core::{PackageId, SourceId, Summary};
11-
use sources::registry::{RegistryPackage, RegistryPackageDefault, INDEX_LOCK};
10+
use sources::registry::{RegistryPackage, INDEX_LOCK};
1211
use sources::registry::RegistryData;
1312
use util::{internal, CargoResult, Config, Filesystem};
1413

@@ -141,7 +140,6 @@ impl<'cfg> RegistryIndex<'cfg> {
141140
///
142141
/// The returned boolean is whether or not the summary has been yanked.
143142
fn parse_registry_package(&mut self, line: &str) -> CargoResult<(Summary, bool)> {
144-
let mut json_de = serde_json::Deserializer::from_str(line);
145143
let RegistryPackage {
146144
name,
147145
vers,
@@ -150,9 +148,11 @@ impl<'cfg> RegistryIndex<'cfg> {
150148
features,
151149
yanked,
152150
links,
153-
} = RegistryPackageDefault(&self.source_id).deserialize(&mut json_de)?;
151+
} = serde_json::from_str(line)?;
154152
let pkgid = PackageId::new(&name, &vers, &self.source_id)?;
155-
let summary = Summary::new(pkgid, deps.inner, features, links)?;
153+
let deps = deps.into_iter().map(|dep| dep.into_dep(&self.source_id))
154+
.collect::<CargoResult<Vec<_>>>()?;
155+
let summary = Summary::new(pkgid, deps, features, links)?;
156156
let summary = summary.set_checksum(cksum.clone());
157157
if self.hashes.contains_key(&name[..]) {
158158
self.hashes.get_mut(&name[..]).unwrap().insert(vers, cksum);

src/cargo/sources/registry/mod.rs

Lines changed: 51 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,11 @@
160160
161161
use std::borrow::Cow;
162162
use std::collections::BTreeMap;
163-
use std::fmt;
164163
use std::fs::File;
165164
use std::path::{Path, PathBuf};
166165

167166
use flate2::read::GzDecoder;
168167
use semver::Version;
169-
use serde::de;
170168
use tar::Archive;
171169

172170
use core::{Package, PackageId, Registry, Source, SourceId, Summary};
@@ -212,29 +210,17 @@ pub struct RegistryConfig {
212210
pub api: Option<String>,
213211
}
214212

213+
#[derive(Deserialize)]
215214
pub struct RegistryPackage<'a> {
216215
name: Cow<'a, str>,
217216
vers: Version,
218-
deps: DependencyList,
217+
deps: Vec<RegistryDependency<'a>>,
219218
features: BTreeMap<String, Vec<String>>,
220219
cksum: String,
221220
yanked: Option<bool>,
222221
links: Option<String>,
223222
}
224223

225-
pub struct RegistryPackageDefault<'a>(pub &'a SourceId);
226-
227-
impl<'de, 'a> de::DeserializeSeed<'de> for RegistryPackageDefault<'a> {
228-
type Value = RegistryPackage<'de>;
229-
230-
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
231-
where
232-
D: de::Deserializer<'de>,
233-
{
234-
deserializer.deserialize_map(self)
235-
}
236-
}
237-
238224
#[derive(Deserialize)]
239225
#[serde(field_identifier, rename_all = "lowercase")]
240226
enum Field {
@@ -247,86 +233,6 @@ enum Field {
247233
Links,
248234
}
249235

250-
impl<'a, 'de> de::Visitor<'de> for RegistryPackageDefault<'a> {
251-
type Value = RegistryPackage<'de>;
252-
253-
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
254-
write!(formatter, "struct RegistryPackage")
255-
}
256-
257-
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
258-
where
259-
A: de::MapAccess<'de>,
260-
{
261-
let mut name = None;
262-
let mut vers = None;
263-
let mut deps = None;
264-
let mut features = None;
265-
let mut cksum = None;
266-
let mut yanked = None;
267-
let mut links = None;
268-
while let Some(key) = map.next_key()? {
269-
match key {
270-
Field::Name => {
271-
if name.is_some() {
272-
return Err(de::Error::duplicate_field("name"));
273-
}
274-
name = Some(map.next_value()?);
275-
}
276-
Field::Vers => {
277-
if vers.is_some() {
278-
return Err(de::Error::duplicate_field("vers"));
279-
}
280-
vers = Some(map.next_value()?);
281-
}
282-
Field::Deps => {
283-
if deps.is_some() {
284-
return Err(de::Error::duplicate_field("deps"));
285-
}
286-
deps = Some(map.next_value_seed(DependencyListDefault(self.0))?);
287-
}
288-
Field::Features => {
289-
if features.is_some() {
290-
return Err(de::Error::duplicate_field("features"));
291-
}
292-
features = Some(map.next_value()?);
293-
}
294-
Field::Cksum => {
295-
if cksum.is_some() {
296-
return Err(de::Error::duplicate_field("cksum"));
297-
}
298-
cksum = Some(map.next_value()?);
299-
}
300-
Field::Yanked => {
301-
if yanked.is_some() {
302-
return Err(de::Error::duplicate_field("yanked"));
303-
}
304-
yanked = Some(map.next_value()?);
305-
}
306-
Field::Links => {
307-
if links.is_some() {
308-
return Err(de::Error::duplicate_field("links"));
309-
}
310-
links = Some(map.next_value()?);
311-
}
312-
}
313-
}
314-
Ok(RegistryPackage {
315-
name: name.ok_or_else(|| de::Error::missing_field("name"))?,
316-
vers: vers.ok_or_else(|| de::Error::missing_field("vers"))?,
317-
deps: deps.ok_or_else(|| de::Error::missing_field("deps"))?,
318-
features: features.ok_or_else(|| de::Error::missing_field("features"))?,
319-
cksum: cksum.ok_or_else(|| de::Error::missing_field("cksum"))?,
320-
yanked: yanked.ok_or_else(|| de::Error::missing_field("yanked"))?,
321-
links: links.unwrap_or(None),
322-
})
323-
}
324-
}
325-
326-
struct DependencyList {
327-
inner: Vec<Dependency>,
328-
}
329-
330236
#[derive(Deserialize)]
331237
struct RegistryDependency<'a> {
332238
name: Cow<'a, str>,
@@ -339,6 +245,55 @@ struct RegistryDependency<'a> {
339245
registry: Option<String>,
340246
}
341247

248+
impl<'a> RegistryDependency<'a> {
249+
/// Converts an encoded dependency in the registry to a cargo dependency
250+
pub fn into_dep(self, default: &SourceId) -> CargoResult<Dependency> {
251+
let RegistryDependency {
252+
name,
253+
req,
254+
mut features,
255+
optional,
256+
default_features,
257+
target,
258+
kind,
259+
registry,
260+
} = self;
261+
262+
let id = if let Some(registry) = registry {
263+
SourceId::for_registry(&registry.to_url()?)?
264+
} else {
265+
default.clone()
266+
};
267+
268+
let mut dep = Dependency::parse_no_deprecated(&name, Some(&req), &id)?;
269+
let kind = match kind.as_ref().map(|s| &s[..]).unwrap_or("") {
270+
"dev" => Kind::Development,
271+
"build" => Kind::Build,
272+
_ => Kind::Normal,
273+
};
274+
275+
let platform = match target {
276+
Some(target) => Some(target.parse()?),
277+
None => None,
278+
};
279+
280+
// Unfortunately older versions of cargo and/or the registry ended up
281+
// publishing lots of entries where the features array contained the
282+
// empty feature, "", inside. This confuses the resolution process much
283+
// later on and these features aren't actually valid, so filter them all
284+
// out here.
285+
features.retain(|s| !s.is_empty());
286+
287+
dep.set_optional(optional)
288+
.set_default_features(default_features)
289+
.set_features(features)
290+
.set_platform(platform)
291+
.set_kind(kind);
292+
293+
Ok(dep)
294+
}
295+
}
296+
342297
pub trait RegistryData {
343298
fn index_path(&self) -> &Filesystem;
344299
fn load(
@@ -543,89 +498,3 @@ impl<'cfg> Source for RegistrySource<'cfg> {
543498
Ok(pkg.package_id().version().to_string())
544499
}
545500
}
546-
547-
struct DependencyListDefault<'a>(&'a SourceId);
548-
549-
impl<'a, 'de> de::DeserializeSeed<'de> for DependencyListDefault<'a> {
550-
type Value = DependencyList;
551-
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
552-
where
553-
D: de::Deserializer<'de>,
554-
{
555-
deserializer.deserialize_seq(self)
556-
}
557-
}
558-
559-
impl<'de, 'a> de::Visitor<'de> for DependencyListDefault<'a> {
560-
type Value = DependencyList;
561-
562-
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
563-
write!(formatter, "a list of dependencies")
564-
}
565-
566-
fn visit_seq<A>(self, mut seq: A) -> Result<DependencyList, A::Error>
567-
where
568-
A: de::SeqAccess<'de>,
569-
{
570-
let mut ret = Vec::new();
571-
if let Some(size) = seq.size_hint() {
572-
ret.reserve(size);
573-
}
574-
while let Some(element) = seq.next_element::<RegistryDependency>()? {
575-
let dep = parse_registry_dependency(element, &self.0).map_err(de::Error::custom)?;
576-
ret.push(dep);
577-
}
578-
579-
Ok(DependencyList { inner: ret })
580-
}
581-
}
582-
583-
/// Converts an encoded dependency in the registry to a cargo dependency
584-
fn parse_registry_dependency(
585-
dep: RegistryDependency,
586-
default: &SourceId,
587-
) -> CargoResult<Dependency> {
588-
let RegistryDependency {
589-
name,
590-
req,
591-
mut features,
592-
optional,
593-
default_features,
594-
target,
595-
kind,
596-
registry,
597-
} = dep;
598-
599-
let id = if let Some(registry) = registry {
600-
SourceId::for_registry(&registry.to_url()?)?
601-
} else {
602-
default.clone()
603-
};
604-
605-
let mut dep = Dependency::parse_no_deprecated(&name, Some(&req), &id)?;
606-
let kind = match kind.as_ref().map(|s| &s[..]).unwrap_or("") {
607-
"dev" => Kind::Development,
608-
"build" => Kind::Build,
609-
_ => Kind::Normal,
610-
};
611-
612-
let platform = match target {
613-
Some(target) => Some(target.parse()?),
614-
None => None,
615-
};
616-
617-
// Unfortunately older versions of cargo and/or the registry ended up
618-
// publishing lots of entries where the features array contained the
619-
// empty feature, "", inside. This confuses the resolution process much
620-
// later on and these features aren't actually valid, so filter them all
621-
// out here.
622-
features.retain(|s| !s.is_empty());
623-
624-
dep.set_optional(optional)
625-
.set_default_features(default_features)
626-
.set_features(features)
627-
.set_platform(platform)
628-
.set_kind(kind);
629-
630-
Ok(dep)
631-
}

0 commit comments

Comments
 (0)