Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update debuginfo for change in 1.71 #241

Merged
merged 1 commit into from
Jul 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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),
}
}
}
Loading