#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MaybeValue<V>(Option<V>);
impl<V> MaybeValue<V> {
#[must_use]
pub fn from_value(value: V) -> Self {
Self(Some(value))
}
#[must_use]
pub fn none() -> Self {
Self(None)
}
#[must_use]
pub fn has_value(&self) -> bool {
self.0.is_some()
}
#[must_use]
pub fn value(&self) -> Option<&V> {
self.0.as_ref()
}
#[must_use]
pub fn into_value(self) -> Option<V> {
self.0
}
#[must_use]
pub fn value_or(self, default: V) -> V {
self.0.unwrap_or(default)
}
#[must_use]
pub fn map<U, F: FnOnce(V) -> U>(self, f: F) -> MaybeValue<U> {
MaybeValue(self.0.map(f))
}
}
impl<V: Clone> MaybeValue<V> {
#[must_use]
pub fn value_or_clone(&self, default: V) -> V {
self.0.clone().unwrap_or(default)
}
}
impl<V: Default> MaybeValue<V> {
#[must_use]
pub fn value_or_default(self) -> V {
self.0.unwrap_or_default()
}
}
impl<V> Default for MaybeValue<V> {
fn default() -> Self {
Self(None)
}
}
impl<V> From<V> for MaybeValue<V> {
fn from(value: V) -> Self {
Self::from_value(value)
}
}
impl<V> From<Option<V>> for MaybeValue<V> {
fn from(option: Option<V>) -> Self {
Self(option)
}
}
impl<V> From<MaybeValue<V>> for Option<V> {
fn from(maybe: MaybeValue<V>) -> Self {
maybe.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn none_has_no_value() {
let m: MaybeValue<i32> = MaybeValue::none();
assert!(!m.has_value());
assert_eq!(m.value(), None);
assert_eq!(MaybeValue::<i32>::default(), MaybeValue::none());
}
#[test]
fn from_value_round_trips() {
let m = MaybeValue::from_value(42);
assert!(m.has_value());
assert_eq!(m.value(), Some(&42));
assert_eq!(Option::from(m), Some(42));
}
#[test]
fn value_or_default_falls_back() {
assert_eq!(MaybeValue::<i32>::none().value_or_default(), 0);
assert_eq!(MaybeValue::from_value(7).value_or_default(), 7);
}
}