|
8 | 8 | //! ```
|
9 | 9 | //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
10 | 10 | //! use std::process::Command;
|
11 |
| -//! use metadata::Metadata; |
| 11 | +//! use docsrs_metadata::Metadata; |
12 | 12 | //!
|
13 | 13 | //! // First, we need to parse Cargo.toml.
|
14 | 14 | //! let source_root = env!("CARGO_MANIFEST_DIR");
|
@@ -36,8 +36,9 @@ use std::collections::{HashMap, HashSet};
|
36 | 36 | use std::io;
|
37 | 37 | use std::path::Path;
|
38 | 38 |
|
| 39 | +use serde::Deserialize; |
39 | 40 | use thiserror::Error;
|
40 |
| -use toml::{map::Map, Value}; |
| 41 | +use toml::Value; |
41 | 42 |
|
42 | 43 | /// The target that `metadata` is being built for.
|
43 | 44 | ///
|
@@ -91,19 +92,23 @@ pub enum MetadataError {
|
91 | 92 | /// ```
|
92 | 93 | ///
|
93 | 94 | /// You can define one or more fields in your `Cargo.toml`.
|
| 95 | +#[derive(Deserialize)] |
| 96 | +#[serde(rename_all = "kebab-case")] |
94 | 97 | pub struct Metadata {
|
95 | 98 | /// List of features to pass on to `cargo`.
|
96 | 99 | ///
|
97 | 100 | /// By default, docs.rs will only build default features.
|
98 | 101 | pub features: Option<Vec<String>>,
|
99 | 102 |
|
100 | 103 | /// Whether to pass `--all-features` to `cargo`.
|
| 104 | + #[serde(default)] |
101 | 105 | pub all_features: bool,
|
102 | 106 |
|
103 | 107 | /// Whether to pass `--no-default-features` to `cargo`.
|
104 | 108 | //
|
105 | 109 | /// 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)] |
107 | 112 | pub no_default_features: bool,
|
108 | 113 |
|
109 | 114 | /// See [`BuildTargets`].
|
@@ -251,63 +256,31 @@ impl std::str::FromStr for Metadata {
|
251 | 256 |
|
252 | 257 | /// Parse the given manifest as TOML.
|
253 | 258 | fn from_str(manifest: &str) -> Result<Metadata, Self::Err> {
|
254 |
| - let mut metadata = Metadata::default(); |
| 259 | + use toml::value::Table; |
255 | 260 |
|
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 | + }; |
269 | 265 |
|
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 | + } |
309 | 271 | }
|
310 | 272 |
|
| 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 | + |
311 | 284 | Ok(metadata)
|
312 | 285 | }
|
313 | 286 | }
|
|
0 commit comments