Skip to content

Commit b5475ca

Browse files
committed
Use serde instead of writing it out by hand
As a side benefit, this has much less copying.
1 parent 7b15aff commit b5475ca

File tree

3 files changed

+31
-56
lines changed

3 files changed

+31
-56
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

metadata/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ description = "Document crates the same way docs.rs would"
1313
path = "lib.rs"
1414

1515
[dependencies]
16+
serde = { version = "1.0", features = ["derive"] }
1617
toml = { version = "0.5", default-features = false }
1718
thiserror = "1"

metadata/lib.rs

+29-56
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
//! ```
99
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
1010
//! use std::process::Command;
11-
//! use metadata::Metadata;
11+
//! use docsrs_metadata::Metadata;
1212
//!
1313
//! // First, we need to parse Cargo.toml.
1414
//! let source_root = env!("CARGO_MANIFEST_DIR");
@@ -36,8 +36,9 @@ use std::collections::{HashMap, HashSet};
3636
use std::io;
3737
use std::path::Path;
3838

39+
use serde::Deserialize;
3940
use thiserror::Error;
40-
use toml::{map::Map, Value};
41+
use toml::Value;
4142

4243
/// The target that `metadata` is being built for.
4344
///
@@ -91,19 +92,23 @@ pub enum MetadataError {
9192
/// ```
9293
///
9394
/// You can define one or more fields in your `Cargo.toml`.
95+
#[derive(Deserialize)]
96+
#[serde(rename_all = "kebab-case")]
9497
pub struct Metadata {
9598
/// List of features to pass on to `cargo`.
9699
///
97100
/// By default, docs.rs will only build default features.
98101
pub features: Option<Vec<String>>,
99102

100103
/// Whether to pass `--all-features` to `cargo`.
104+
#[serde(default)]
101105
pub all_features: bool,
102106

103107
/// Whether to pass `--no-default-features` to `cargo`.
104108
//
105109
/// By default, Docs.rs will build default features.
106-
/// Set `no-default-fatures` to `false` if you want to build only certain features.
110+
/// Set `no-default-fatures` to `true` if you want to build only certain features.
111+
#[serde(default)]
107112
pub no_default_features: bool,
108113

109114
/// See [`BuildTargets`].
@@ -251,63 +256,31 @@ impl std::str::FromStr for Metadata {
251256

252257
/// Parse the given manifest as TOML.
253258
fn from_str(manifest: &str) -> Result<Metadata, Self::Err> {
254-
let mut metadata = Metadata::default();
259+
use toml::value::Table;
255260

256-
let manifest = manifest.parse::<Value>()?;
257-
258-
fn fetch_manifest_tables<'a>(manifest: &'a Value) -> Option<&'a Map<String, Value>> {
259-
manifest
260-
.get("package")?
261-
.as_table()?
262-
.get("metadata")?
263-
.as_table()?
264-
.get("docs")?
265-
.as_table()?
266-
.get("rs")?
267-
.as_table()
268-
}
261+
let manifest = match manifest.parse::<Value>()? {
262+
Value::Table(t) => Some(t),
263+
_ => None,
264+
};
269265

270-
if let Some(table) = fetch_manifest_tables(&manifest) {
271-
// TODO: all this `to_owned` is inefficient, this should use explicit matches instead.
272-
let collect_into_array =
273-
|f: &Vec<Value>| f.iter().map(|v| v.as_str().map(|v| v.to_owned())).collect();
274-
275-
metadata.features = table
276-
.get("features")
277-
.and_then(|f| f.as_array())
278-
.and_then(collect_into_array);
279-
280-
metadata.no_default_features = table
281-
.get("no-default-features")
282-
.and_then(|v| v.as_bool())
283-
.unwrap_or(metadata.no_default_features);
284-
285-
metadata.all_features = table
286-
.get("all-features")
287-
.and_then(|v| v.as_bool())
288-
.unwrap_or(metadata.all_features);
289-
290-
metadata.default_target = table
291-
.get("default-target")
292-
.and_then(|v| v.as_str())
293-
.map(|v| v.to_owned());
294-
295-
metadata.targets = table
296-
.get("targets")
297-
.and_then(|f| f.as_array())
298-
.and_then(collect_into_array);
299-
300-
metadata.rustc_args = table
301-
.get("rustc-args")
302-
.and_then(|f| f.as_array())
303-
.and_then(collect_into_array);
304-
305-
metadata.rustdoc_args = table
306-
.get("rustdoc-args")
307-
.and_then(|f| f.as_array())
308-
.and_then(collect_into_array);
266+
fn table<'a>(mut manifest: Table, table_name: &str) -> Option<Table> {
267+
match manifest.remove(table_name) {
268+
Some(Value::Table(table)) => Some(table),
269+
_ => None,
270+
}
309271
}
310272

273+
let table = manifest
274+
.and_then(|t| table(t, "package"))
275+
.and_then(|t| table(t, "metadata"))
276+
.and_then(|t| table(t, "docs"))
277+
.and_then(|t| table(t, "rs"));
278+
let metadata = if let Some(table) = table {
279+
Value::Table(table).try_into()?
280+
} else {
281+
Metadata::default()
282+
};
283+
311284
Ok(metadata)
312285
}
313286
}

0 commit comments

Comments
 (0)