Skip to content

Commit

Permalink
Merge pull request #241 from ehuss/artifact-debuginfo
Browse files Browse the repository at this point in the history
Update debuginfo for change in 1.71
  • Loading branch information
oli-obk committed Jul 19, 2023
2 parents 56fcbaa + 0ee32c8 commit 14a8b64
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 6 deletions.
3 changes: 2 additions & 1 deletion src/lib.rs
Expand Up @@ -102,7 +102,8 @@ 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::{
Expand Down
135 changes: 131 additions & 4 deletions src/messages.rs
Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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))]
Expand Down
47 changes: 46 additions & 1 deletion tests/test_samples.rs
Expand Up @@ -4,7 +4,9 @@ extern crate semver;
extern crate serde_json;

use camino::Utf8PathBuf;
use cargo_metadata::{CargoOpt, DependencyKind, Edition, Metadata, MetadataCommand};
use cargo_metadata::{
ArtifactDebuginfo, CargoOpt, DependencyKind, Edition, Message, Metadata, MetadataCommand,
};

#[test]
fn old_minimal() {
Expand Down Expand Up @@ -645,3 +647,46 @@ fn basic_workspace_root_package_exists() {
"ex_bin"
);
}

#[test]
fn debuginfo_variants() {
// Checks behavior for the different debuginfo variants.
let variants = [
("0", ArtifactDebuginfo::None),
("1", ArtifactDebuginfo::Limited),
("2", ArtifactDebuginfo::Full),
(
"\"line-directives-only\"",
ArtifactDebuginfo::LineDirectivesOnly,
),
("\"line-tables-only\"", ArtifactDebuginfo::LineTablesOnly),
("3", ArtifactDebuginfo::UnknownInt(3)),
(
"\"abc\"",
ArtifactDebuginfo::UnknownString("abc".to_string()),
),
("null", ArtifactDebuginfo::None),
];
for (value, expected) in variants {
let s = r#"{"reason":"compiler-artifact","package_id":"cargo_metadata 0.16.0 (path+file:////cargo_metadata)","manifest_path":"/cargo_metadata/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cargo_metadata","src_path":"/cargo_metadata/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":DEBUGINFO,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/cargo_metadata/target/debug/deps/libcargo_metadata-27f582f7187b9a2c.rmeta"],"executable":null,"fresh":false}"#;
let message: Message = serde_json::from_str(&s.replace("DEBUGINFO", value)).unwrap();
match message {
Message::CompilerArtifact(artifact) => {
assert_eq!(artifact.profile.debuginfo, expected);
let de_s = serde_json::to_string(&artifact.profile.debuginfo).unwrap();
// Note: Roundtrip does not retain null value.
if value == "null" {
assert_eq!(artifact.profile.debuginfo.to_string(), "0");
assert_eq!(de_s, "0");
} else {
assert_eq!(
artifact.profile.debuginfo.to_string(),
value.trim_matches('"')
);
assert_eq!(de_s, value);
}
}
_ => panic!("unexpected {:?}", message),
}
}
}

0 comments on commit 14a8b64

Please sign in to comment.