|
| 1 | +//! Deserialization of a `Value<T>` type which tracks where it was deserialized |
| 2 | +//! from. |
| 3 | +//! |
| 4 | +//! Often Cargo wants to report semantic error information or other sorts of |
| 5 | +//! error information about configuration keys but it also may wish to indicate |
| 6 | +//! as an error context where the key was defined as well (to help user |
| 7 | +//! debugging). The `Value<T>` type here can be used to deserialize a `T` value |
| 8 | +//! from configuration, but also record where it was deserialized from when it |
| 9 | +//! was read. |
| 10 | +
|
1 | 11 | use crate::util::config::Config;
|
2 | 12 | use serde::de;
|
3 | 13 | use std::fmt;
|
4 | 14 | use std::marker;
|
5 | 15 | use std::mem;
|
6 | 16 | use std::path::{Path, PathBuf};
|
7 | 17 |
|
| 18 | +/// A type which can be deserialized as a configuration value which records |
| 19 | +/// where it was deserialized from. |
8 | 20 | #[derive(Debug, PartialEq, Clone)]
|
9 | 21 | pub struct Value<T> {
|
| 22 | + /// The inner value that was deserialized. |
10 | 23 | pub val: T,
|
| 24 | + /// The location where `val` was defined in configuration (e.g. file it was |
| 25 | + /// defined in, env var etc). |
11 | 26 | pub definition: Definition,
|
12 | 27 | }
|
13 | 28 |
|
14 | 29 | pub type OptValue<T> = Option<Value<T>>;
|
15 | 30 |
|
| 31 | +// Deserializing `Value<T>` is pretty special, and serde doesn't have built-in |
| 32 | +// support for this operation. To implement this we extend serde's "data model" |
| 33 | +// a bit. We configure deserialization of `Value<T>` to basically only work with |
| 34 | +// our one deserializer using configuration. |
| 35 | +// |
| 36 | +// We define that `Value<T>` deserialization asks the deserializer for a very |
| 37 | +// special struct name and struct field names. In doing so the deserializer will |
| 38 | +// recognize this and synthesize a magical value for the `definition` field when |
| 39 | +// we deserialize it. This protocol is how we're able to have a channel of |
| 40 | +// information flowing from the configuration deserializer into the |
| 41 | +// deserialization implementation here. |
| 42 | +// |
| 43 | +// You'll want to also check out the implementation of `ValueDeserializer` in |
| 44 | +// `de.rs`. Also note that the names below are intended to be invalid Rust |
| 45 | +// identifiers to avoid how they might conflict with other valid structures. |
| 46 | +// Finally the `definition` field is transmitted as a tuple of i32/string, which |
| 47 | +// is effectively a tagged union of `Definition` itself. |
| 48 | + |
16 | 49 | pub(crate) const VALUE_FIELD: &str = "$__cargo_private_value";
|
17 | 50 | pub(crate) const DEFINITION_FIELD: &str = "$__cargo_private_definition";
|
18 | 51 | pub(crate) const NAME: &str = "$__cargo_private_Value";
|
|
0 commit comments