Repository: oli-obk/cargo_metadata
Pull request #27 (2018-01-06 13:04:32)

Implement `Serialize` on everything


Patch:
diff --git a/README.md b/README.md
index 7bc0aba..853aaf5 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,10 @@
 
 Structured access to the output of `cargo metadata`. Usually used from within a `cargo-*` executable.
 
+Also supports serialization to aid in implementing `--message-format=json`-like
+output generation in `cargo-*` subcommands, since some of the types in what
+`cargo --message-format=json` emits are exactly the same as the ones from `cargo metadata`.
+
 [![Build Status](https://api.travis-ci.org/oli-obk/cargo_metadata.svg?branch=master)](https://travis-ci.org/oli-obk/cargo_metadata)
 [![crates.io](https://img.shields.io/crates/v/cargo_metadata.svg)](https://crates.io/crates/cargo_metadata)
 
diff --git a/src/dependency.rs b/src/dependency.rs
index 5caf014..3a21d63 100644
--- a/src/dependency.rs
+++ b/src/dependency.rs
@@ -3,7 +3,7 @@
 use serde::{Deserialize, Deserializer};
 use semver::VersionReq;
 
-#[derive(PartialEq, Clone, Debug, Copy, Deserialize)]
+#[derive(PartialEq, Clone, Debug, Copy, Serialize, Deserialize)]
 /// Dependencies can come in three kinds
 pub enum DependencyKind {
     #[serde(rename = "normal")]
@@ -33,7 +33,7 @@ where
     Deserialize::deserialize(d).map(|x: Option<_>| x.unwrap_or_default())
 }
 
-#[derive(Clone, Deserialize, Debug)]
+#[derive(Clone, Serialize, Deserialize, Debug)]
 /// A dependency of the main crate
 pub struct Dependency {
     /// Name as given in the `Cargo.toml`
diff --git a/src/lib.rs b/src/lib.rs
index f3ce106..afa374c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -86,15 +86,16 @@ use std::env;
 use std::path::Path;
 use std::process::Command;
 use std::str::from_utf8;
+use std::fmt::Write;
 
 pub use errors::{Error, ErrorKind, Result};
 pub use dependency::{Dependency, DependencyKind};
-use serde::de;
+use serde::{ser, de, Serializer};
 
 mod errors;
 mod dependency;
 
-#[derive(Clone, Deserialize, Debug)]
+#[derive(Clone, Serialize, Deserialize, Debug)]
 /// Starting point for metadata returned by `cargo metadata`
 pub struct Metadata {
     /// A list of all crates referenced by this crate (and the crate itself)
@@ -109,7 +110,7 @@ pub struct Metadata {
     __do_not_match_exhaustively: (),
 }
 
-#[derive(Clone, Deserialize, Debug)]
+#[derive(Clone, Serialize, Deserialize, Debug)]
 /// A dependency graph
 pub struct Resolve {
     /// Nodes in a dependencies graph
@@ -119,7 +120,7 @@ pub struct Resolve {
     __do_not_match_exhaustively: (),
 }
 
-#[derive(Clone, Deserialize, Debug)]
+#[derive(Clone, Serialize, Deserialize, Debug)]
 /// A node in a dependencies graph
 pub struct Node {
     /// An opaque identifier for a package
@@ -131,7 +132,7 @@ pub struct Node {
     __do_not_match_exhaustively: (),
 }
 
-#[derive(Clone, Deserialize, Debug)]
+#[derive(Clone, Serialize, Deserialize, Debug)]
 /// A crate
 pub struct Package {
     /// Name as given in the `Cargo.toml`
@@ -154,7 +155,7 @@ pub struct Package {
     __do_not_match_exhaustively: (),
 }
 
-#[derive(Clone, Deserialize, Debug)]
+#[derive(Clone, Serialize, Deserialize, Debug)]
 /// A single target (lib, bin, example, ...) provided by a crate
 pub struct Target {
     /// Name as given in the `Cargo.toml` or generated from the file name
@@ -207,6 +208,17 @@ impl<'de> de::Deserialize<'de> for WorkspaceMember {
     }
 }
 
+impl ser::Serialize for WorkspaceMember {
+    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
+    where
+        S: Serializer
+    {
+        let mut output = String::new();
+        write!(output, "{} {} ({})", self.name, self.version, self.url).unwrap();
+        serializer.serialize_str(&output)
+    }
+}
+
 /// Obtain metadata only about the root package and don't fetch dependencies
 ///
 /// # Parameters


Test patch:
diff --git a/tests/selftest.rs b/tests/selftest.rs
index a5dffd0..4082b7f 100644
--- a/tests/selftest.rs
+++ b/tests/selftest.rs
@@ -1,5 +1,6 @@
 extern crate cargo_metadata;
 extern crate semver;
+extern crate serde_json;
 
 use std::path::Path;
 
@@ -53,3 +54,15 @@ fn metadata_deps() {
     assert!(serde.req.matches(&Version::parse("1.99.99").unwrap()));
     assert!(!serde.req.matches(&Version::parse("2.0.0").unwrap()));
 }
+
+#[test]
+fn workspace_member_serialization_deserialization() {
+    let original = "\"security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)\"";
+    let member: cargo_metadata::WorkspaceMember = serde_json::from_str(original).unwrap();
+    assert_eq!(member.name, "security-framework");
+    assert_eq!(member.version, Version::new(0, 1, 16));
+    assert_eq!(member.url, "registry+https://github.com/rust-lang/crates.io-index");
+
+    let serialized = serde_json::to_string(&member).unwrap();
+    assert_eq!(serialized, original);
+}