diff options
Diffstat (limited to 'vendor/cargo_metadata/src')
-rw-r--r-- | vendor/cargo_metadata/src/lib.rs | 118 | ||||
-rw-r--r-- | vendor/cargo_metadata/src/messages.rs | 135 |
2 files changed, 226 insertions, 27 deletions
diff --git a/vendor/cargo_metadata/src/lib.rs b/vendor/cargo_metadata/src/lib.rs index 627511773..c222c130e 100644 --- a/vendor/cargo_metadata/src/lib.rs +++ b/vendor/cargo_metadata/src/lib.rs @@ -81,7 +81,7 @@ use camino::Utf8PathBuf; #[cfg(feature = "builder")] use derive_builder::Builder; -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; use std::env; use std::ffi::OsString; use std::fmt; @@ -92,7 +92,7 @@ use std::str::from_utf8; pub use camino; pub use semver; -use semver::{Version, VersionReq}; +use semver::Version; #[cfg(feature = "builder")] pub use dependency::DependencyBuilder; @@ -102,14 +102,15 @@ pub use errors::{Error, Result}; #[allow(deprecated)] pub use messages::parse_messages; pub use messages::{ - Artifact, ArtifactProfile, BuildFinished, BuildScript, CompilerMessage, Message, MessageIter, + Artifact, ArtifactDebuginfo, ArtifactProfile, BuildFinished, BuildScript, CompilerMessage, + Message, MessageIter, }; #[cfg(feature = "builder")] pub use messages::{ ArtifactBuilder, ArtifactProfileBuilder, BuildFinishedBuilder, BuildScriptBuilder, CompilerMessageBuilder, }; -use serde::{Deserialize, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize}; mod dependency; pub mod diagnostic; @@ -117,6 +118,7 @@ mod errors; mod messages; /// An "opaque" identifier for a package. +/// /// It is possible to inspect the `repr` field, if the need arises, but its /// precise format is an implementation detail and is subject to change. /// @@ -128,7 +130,7 @@ pub struct PackageId { pub repr: String, } -impl std::fmt::Display for PackageId { +impl fmt::Display for PackageId { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.repr, f) } @@ -139,18 +141,6 @@ fn is_null(value: &serde_json::Value) -> bool { matches!(value, serde_json::Value::Null) } -/// Helper to ensure that hashmaps serialize in sorted order, to make -/// serialization deterministic. -fn sorted_map<S: Serializer, K: Serialize + Ord, V: Serialize>( - value: &HashMap<K, V>, - serializer: S, -) -> std::result::Result<S::Ok, S::Error> { - value - .iter() - .collect::<BTreeMap<_, _>>() - .serialize(serializer) -} - #[derive(Clone, Serialize, Deserialize, Debug)] #[cfg_attr(feature = "builder", derive(Builder))] #[non_exhaustive] @@ -323,8 +313,7 @@ pub struct Package { /// Targets provided by the crate (lib, bin, example, test, ...) pub targets: Vec<Target>, /// Features provided by the crate, mapped to the features required by that feature. - #[serde(serialize_with = "sorted_map")] - pub features: HashMap<String, Vec<String>>, + pub features: BTreeMap<String, Vec<String>>, /// Path containing the `Cargo.toml` pub manifest_path: Utf8PathBuf, /// Categories as given in the `Cargo.toml` @@ -392,7 +381,9 @@ pub struct Package { /// The minimum supported Rust version of this package. /// /// This is always `None` if running with a version of Cargo older than 1.58. - pub rust_version: Option<VersionReq>, + #[serde(default)] + #[serde(deserialize_with = "deserialize_rust_version")] + pub rust_version: Option<Version>, } impl Package { @@ -418,6 +409,9 @@ impl Package { } /// The source of a package such as crates.io. +/// +/// It is possible to inspect the `repr` field, if the need arises, but its +/// precise format is an implementation detail and is subject to change. #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] #[serde(transparent)] pub struct Source { @@ -432,7 +426,7 @@ impl Source { } } -impl std::fmt::Display for Source { +impl fmt::Display for Source { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.repr, f) } @@ -615,7 +609,7 @@ pub struct MetadataCommand { other_options: Vec<String>, /// Arbitrary environment variables to set when running `cargo`. These will be merged into /// the calling environment, overriding any which clash. - env: HashMap<OsString, OsString>, + env: BTreeMap<OsString, OsString>, /// Show stderr verbose: bool, } @@ -754,7 +748,7 @@ impl MetadataCommand { .or_else(|| env::var("CARGO").map(PathBuf::from).ok()) .unwrap_or_else(|| PathBuf::from("cargo")); let mut cmd = Command::new(cargo); - cmd.args(&["metadata", "--format-version", "1"]); + cmd.args(["metadata", "--format-version", "1"]); if self.no_deps { cmd.arg("--no-deps"); @@ -810,3 +804,81 @@ impl MetadataCommand { Self::parse(stdout) } } + +/// As per the Cargo Book the [`rust-version` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-rust-version-field) must: +/// +/// > be a bare version number with two or three components; +/// > it cannot include semver operators or pre-release identifiers. +/// +/// [`semver::Version`] however requires three components. This function takes +/// care of appending `.0` if the provided version number only has two components +/// and ensuring that it does not contain a pre-release version or build metadata. +fn deserialize_rust_version<'de, D>( + deserializer: D, +) -> std::result::Result<Option<Version>, D::Error> +where + D: Deserializer<'de>, +{ + let mut buf = match Option::<String>::deserialize(deserializer)? { + None => return Ok(None), + Some(buf) => buf, + }; + + for char in buf.chars() { + if char == '-' { + return Err(serde::de::Error::custom( + "pre-release identifiers are not supported in rust-version", + )); + } else if char == '+' { + return Err(serde::de::Error::custom( + "build metadata is not supported in rust-version", + )); + } + } + + if buf.matches('.').count() == 1 { + // e.g. 1.0 -> 1.0.0 + buf.push_str(".0"); + } + + Ok(Some( + Version::parse(&buf).map_err(serde::de::Error::custom)?, + )) +} + +#[cfg(test)] +mod test { + use semver::Version; + + #[derive(Debug, serde::Deserialize)] + struct BareVersion( + #[serde(deserialize_with = "super::deserialize_rust_version")] Option<semver::Version>, + ); + + fn bare_version(str: &str) -> Version { + serde_json::from_str::<BareVersion>(&format!(r#""{}""#, str)) + .unwrap() + .0 + .unwrap() + } + + fn bare_version_err(str: &str) -> String { + serde_json::from_str::<BareVersion>(&format!(r#""{}""#, str)) + .unwrap_err() + .to_string() + } + + #[test] + fn test_deserialize_rust_version() { + assert_eq!(bare_version("1.2"), Version::new(1, 2, 0)); + assert_eq!(bare_version("1.2.0"), Version::new(1, 2, 0)); + assert_eq!( + bare_version_err("1.2.0-alpha"), + "pre-release identifiers are not supported in rust-version" + ); + assert_eq!( + bare_version_err("1.2.0+123"), + "build metadata is not supported in rust-version" + ); + } +} diff --git a/vendor/cargo_metadata/src/messages.rs b/vendor/cargo_metadata/src/messages.rs index ea2abd250..028cd726e 100644 --- a/vendor/cargo_metadata/src/messages.rs +++ b/vendor/cargo_metadata/src/messages.rs @@ -2,8 +2,8 @@ use super::{Diagnostic, PackageId, Target}; use camino::Utf8PathBuf; #[cfg(feature = "builder")] use derive_builder::Builder; -use serde::{Deserialize, Serialize}; -use std::fmt; +use serde::{de, ser, Deserialize, Serialize}; +use std::fmt::{self, Write}; use std::io::{self, BufRead, Read}; /// Profile settings used to determine which compiler flags to use for a @@ -15,8 +15,9 @@ use std::io::{self, BufRead, Read}; pub struct ArtifactProfile { /// Optimization level. Possible values are 0-3, s or z. pub opt_level: String, - /// The amount of debug info. 0 for none, 1 for limited, 2 for full - pub debuginfo: Option<u32>, + /// The kind of debug information. + #[serde(default)] + pub debuginfo: ArtifactDebuginfo, /// State of the `cfg(debug_assertions)` directive, enabling macros like /// `debug_assert!` pub debug_assertions: bool, @@ -26,6 +27,132 @@ pub struct ArtifactProfile { pub test: bool, } +/// The kind of debug information included in the artifact. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum ArtifactDebuginfo { + /// No debug information. + None, + /// Line directives only. + LineDirectivesOnly, + /// Line tables only. + LineTablesOnly, + /// Debug information without type or variable-level information. + Limited, + /// Full debug information. + Full, + /// An unknown integer level. + /// + /// This may be produced by a version of rustc in the future that has + /// additional levels represented by an integer that are not known by this + /// version of `cargo_metadata`. + UnknownInt(i64), + /// An unknown string level. + /// + /// This may be produced by a version of rustc in the future that has + /// additional levels represented by a string that are not known by this + /// version of `cargo_metadata`. + UnknownString(String), +} + +impl Default for ArtifactDebuginfo { + fn default() -> Self { + ArtifactDebuginfo::None + } +} + +impl ser::Serialize for ArtifactDebuginfo { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + match self { + Self::None => 0.serialize(serializer), + Self::LineDirectivesOnly => "line-directives-only".serialize(serializer), + Self::LineTablesOnly => "line-tables-only".serialize(serializer), + Self::Limited => 1.serialize(serializer), + Self::Full => 2.serialize(serializer), + Self::UnknownInt(n) => n.serialize(serializer), + Self::UnknownString(s) => s.serialize(serializer), + } + } +} + +impl<'de> de::Deserialize<'de> for ArtifactDebuginfo { + fn deserialize<D>(d: D) -> Result<ArtifactDebuginfo, D::Error> + where + D: de::Deserializer<'de>, + { + struct Visitor; + + impl<'de> de::Visitor<'de> for Visitor { + type Value = ArtifactDebuginfo; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("an integer or string") + } + + fn visit_i64<E>(self, value: i64) -> Result<ArtifactDebuginfo, E> + where + E: de::Error, + { + let debuginfo = match value { + 0 => ArtifactDebuginfo::None, + 1 => ArtifactDebuginfo::Limited, + 2 => ArtifactDebuginfo::Full, + n => ArtifactDebuginfo::UnknownInt(n), + }; + Ok(debuginfo) + } + + fn visit_u64<E>(self, value: u64) -> Result<ArtifactDebuginfo, E> + where + E: de::Error, + { + self.visit_i64(value as i64) + } + + fn visit_str<E>(self, value: &str) -> Result<ArtifactDebuginfo, E> + where + E: de::Error, + { + let debuginfo = match value { + "none" => ArtifactDebuginfo::None, + "limited" => ArtifactDebuginfo::Limited, + "full" => ArtifactDebuginfo::Full, + "line-directives-only" => ArtifactDebuginfo::LineDirectivesOnly, + "line-tables-only" => ArtifactDebuginfo::LineTablesOnly, + s => ArtifactDebuginfo::UnknownString(s.to_string()), + }; + Ok(debuginfo) + } + + fn visit_unit<E>(self) -> Result<ArtifactDebuginfo, E> + where + E: de::Error, + { + Ok(ArtifactDebuginfo::None) + } + } + + d.deserialize_any(Visitor) + } +} + +impl fmt::Display for ArtifactDebuginfo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ArtifactDebuginfo::None => f.write_char('0'), + ArtifactDebuginfo::Limited => f.write_char('1'), + ArtifactDebuginfo::Full => f.write_char('2'), + ArtifactDebuginfo::LineDirectivesOnly => f.write_str("line-directives-only"), + ArtifactDebuginfo::LineTablesOnly => f.write_str("line-tables-only"), + ArtifactDebuginfo::UnknownInt(n) => write!(f, "{}", n), + ArtifactDebuginfo::UnknownString(s) => f.write_str(s), + } + } +} + /// A compiler-generated file. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] #[cfg_attr(feature = "builder", derive(Builder))] |