https://github.com/brahmlower/default-aware
A tiny struct for indicating if a value was generated via the Default trait or not.
https://github.com/brahmlower/default-aware
rust
Last synced: over 1 year ago
JSON representation
A tiny struct for indicating if a value was generated via the Default trait or not.
- Host: GitHub
- URL: https://github.com/brahmlower/default-aware
- Owner: brahmlower
- Created: 2023-08-15T06:55:50.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2023-08-21T01:45:39.000Z (almost 3 years ago)
- Last Synced: 2024-05-02T06:10:05.235Z (about 2 years ago)
- Topics: rust
- Language: Rust
- Homepage: https://crates.io/crates/default_aware
- Size: 6.84 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
Awesome Lists containing this project
README
# Default-Aware
A tiny struct for indicating if a value was generated via the Default trait or not.
Installation:
```toml
[dependencies]
default_aware = "0.1.0"
```
## Usage
If you're deserializing a struct and want to behavior based on a value being explicitly set or not, you can use the `DefaultAware` struct to wrap the type in question, and then inspect it after derserializing to see if the value was created by the `Default` trait, or if it came from the deserialized source:
```rust
use default_aware::DefaultAware;
use serde::{self, Deserialize};
use serde_json;
// This represents some value you might deserialize, which
// implements the `Default` trait.
#[derive(Deserialize, PartialEq, Debug)]
struct Port(u32);
impl Default for Port {
fn default() -> Self {
Port(8000)
}
}
#[derive(Deserialize)]
pub struct MyConfig {
#[serde(default)]
http_port: DefaultAware,
}
fn main() {
// The first config sets the port number to the same as the
// default. If we weren't using the `DefaultAware` wrapper, the
// value recieved after deserializing would be
// indistinguishable from the default value. Therefore we could
// not know if the `http_port` field was actually provided in
// the document or not.
let config1_json: &str = r#"{ "http_port": 8000 }"#;
// But since we are using the `DefaultAware` wrapper, we can
// easily tell that the value was not created via the `Default`
// implementation.
let config1: MyConfig = serde_json::from_str(config1_json)
.unwrap();
assert_eq!(false, config1.http_port.is_default());
assert_eq!(Port(8000), config1.http_port.unwrap());
// We can demonstrate the behavior when the default value is
// used by checking the output
// on a document that omits the `http_port` field.
const config2_json: &str = r#"{ }"#;
// The field has the same wrapped value as before, but notice
// that we tell it was created via the Default implementation.
let config2: MyConfig = serde_json::from_str(config2_json)
.unwrap();
assert_eq!(Port(8000), *config2.http_port.as_ref());
assert_eq!(true, config2.http_port.is_default());
// The type is just an enun, so we can use all the typical enum
// patterns
match config2.http_port {
DefaultAware::Default(_) =>
println!("value set by default"),
DefaultAware::Declared(_) =>
println!("value set in the config"),
}
if let DefaultAware::Default(_) = config2.http_port {
println!("Port number not set! Running on port 8000 by \
default. Silence this warning by setting the \
`http_port` field in your config.");
}
}
```
## Features
Serde functionality is guarded by the feature `serde` and is enabled by default. You can use this crate without serde by listing the dependency like so:
```toml
[dependencies]
default_aware = { version = "0.1.0", default-features = false }
```