Rust library providing a three state enum for differentiating between an explicit null value and the absense of a value. This is intended to be used with serde
serialization and deserialization to address an ambiguity between null values and the absense of a value where Option
comflates the two.
Possible
is an enumerator over three possibilities Some(T)
, None
, and Void
. The intended use is that Some(T)
is used for storing some data like with an Option
; None
represents explicitly null values; and Void
represents the absense of any value.
Possible
implements most of the same functionality as Option
, and can often be used as a direct replacement. Even though there is disambiguation between None
and Void
, they will tend to be treated in the same way for most Option
functionality to behave in an expected way.
With cargo-edit, run the following to add this library to your project.
sh
cargo add possible
Otherwise add the following to the Cargo.toml
file of your project under the [dependencies]
table section.
```toml
possible = "0.1.0" ```
In it's most simple case, Possible
can be used in similar ways to Option
.
```rust use possible::Possible;
let possiblevalue: Possible
if let Possible::Some(value) = possiblevalue { asserteq!(value, 42); }
let halvedpossiblevalue = possiblevalue.map(|value| value / 2); asserteq!(halvedpossiblevalue, Possible::Some(21));
let unwrappedvalue = possiblevalue.unwrap(); asserteq!(unwrappedvalue, 42); ```
Matching can be done similarly to Option
type variants.
```rust use possible::Possible;
let possible_value: Possible
if let Possible::Void = possible_value { // semantically means there is an absense of any value stored }
match possible_value { Possible::Void => { /* the default variant implying no value / } Possible::None => { / like Option::None, a null or empty value / } Possible::Some(value) => { / like Option::Some, a value of some type */ } }
asserteq!(possiblevalue.isvoid(), true); asserteq!(possiblevalue.isnone(), false); asserteq!(possiblevalue.is_some(), false); ```
The primary use case for this library is paired with serde
serialization and deserialization from formats like JSON. This is useful when the a null value (or None
) is a valid value yet the absence of a value is still significant to capture.
```rust use serde::Serialize; use serde_json::json; use possible::Possible;
// serde(skipserializingif = "Possible::is_void") is required to implicitly // omit values that are set as Possible::Void from being serialized
pub struct OutputJsonData { id: i64,
#[serde(skip_serializing_if = "Possible::is_void")]
name: Possible<String>,
#[serde(skip_serializing_if = "Possible::is_void")]
enabled: Possible<bool>,
}
let intended_output = OutputJsonData { id: 1324, name: Possible::Void, enabled: Possible::Some(true), };
let serialized = serdejson::tostring(&intendedoutput).unwrap(); asserteq!(serialized, r#"{"id":1324,"enabled":true}"#); ```
```rust use serde::Deserialize; use possible::Possible;
let input = r#"{ "id": 1324, "name": "Ferris" }"#;
// serde(default) is required to implicitly parse // missing values as Possible::Void instead of Possible::None
pub struct InputJsonData { id: i64,
#[serde(default)]
name: Possible<String>,
#[serde(default)]
enabled: Possible<bool>,
}
let parsedinput: InputJsonData = serdejson::fromstr(input).unwrap(); asserteq!(parsed_input, InputJsonData { id: 1324, name: Possible::Some( String::from("Ferris") ), enabled: Possible::Void, }); ```
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.