use crate::{Enumerable, Listable, Mappable, Structable, Tuplable, Valuable, Visit}; use core::fmt; macro_rules! value { ( $( $(#[$attrs:meta])* $variant:ident($ty:ty), )* ) => { /// Any Rust value /// /// The `Value` enum is used to pass single values to the /// [visitor][`Visit`]. Primitive types are enumerated and other types /// are represented at trait objects. /// /// Values are converted to `Value` instances using /// [`Valuable::as_value()`]. /// /// # Examples /// /// Convert a primitive type /// /// ``` /// use valuable::{Value, Valuable}; /// /// let num = 123; /// let val = num.as_value(); /// /// assert!(matches!(val, Value::I32(v) if v == 123)); /// ``` /// /// Converting a struct /// /// ``` /// use valuable::{Value, Valuable}; /// /// #[derive(Valuable, Debug)] /// struct HelloWorld { /// message: String, /// } /// /// let hello = HelloWorld { /// message: "greetings".to_string(), /// }; /// /// let val = hello.as_value(); /// /// assert!(matches!(val, Value::Structable(_v))); /// /// // The Value `Debug` output matches the struct's /// assert_eq!( /// format!("{:?}", val), /// format!("{:?}", hello), /// ); /// ``` /// /// [visitor]: Visit #[non_exhaustive] #[derive(Clone, Copy)] pub enum Value<'a> { $( $(#[$attrs])* $variant($ty), )* /// A Rust `()` or `None` value. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::Unit; /// ``` Unit, } $( $(#[$attrs])* impl<'a> From<$ty> for Value<'a> { fn from(src: $ty) -> Value<'a> { Value::$variant(src) } } )* impl<'a> From<()> for Value<'a> { fn from(_: ()) -> Value<'a> { Value::Tuplable(&()) } } impl fmt::Debug for Value<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { use Value::*; // Doc comments are expanded into the branch arms, which results // in a warning. It isn't a big deal, so silence it. #[allow(unused_doc_comments)] match self { $( $(#[$attrs])* $variant(v) => fmt::Debug::fmt(v, fmt), )* Unit => ().fmt(fmt), } } } } } value! { /// A Rust `bool` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::Bool(true); /// ``` Bool(bool), /// A Rust `char` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::Char('h'); /// ``` Char(char), /// A Rust `f32` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::F32(3.1415); /// ``` F32(f32), /// A Rust `f64` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::F64(3.1415); /// ``` F64(f64), /// A Rust `i8` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::I8(42); /// ``` I8(i8), /// A Rust `i16` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::I16(42); /// ``` I16(i16), /// A Rust `i32` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::I32(42); /// ``` I32(i32), /// A Rust `i64` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::I64(42); /// ``` I64(i64), /// A Rust `i128` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::I128(42); /// ``` I128(i128), /// A Rust `isize` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::Isize(42); /// ``` Isize(isize), /// A Rust `&str` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::String("hello"); /// ``` String(&'a str), /// A Rust `u8` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::U8(42); /// ``` U8(u8), /// A Rust `u16` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::U16(42); /// ``` U16(u16), /// A Rust `u32` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::U32(42); /// ``` U32(u32), /// A Rust `u64` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::U64(42); /// ``` U64(u64), /// A Rust `u128` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::U128(42); /// ``` U128(u128), /// A Rust `usize` value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let v = Value::Usize(42); /// ``` Usize(usize), /// A Rust `&Path` value /// /// # Examples /// /// ``` /// use valuable::Value; /// use std::path::Path; /// /// let path = Path::new("a.txt"); /// let v = Value::Path(path); /// ``` #[cfg(feature = "std")] Path(&'a std::path::Path), /// A Rust error value /// /// # Examples /// /// ``` /// use valuable::Value; /// use std::io; /// /// let err: io::Error = io::ErrorKind::Other.into(); /// let v = Value::Error(&err); /// ``` #[cfg(feature = "std")] Error(&'a (dyn std::error::Error +'static)), /// A Rust list value /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let vals = vec![1, 2, 3, 4, 5]; /// let v = Value::Listable(&vals); /// ``` Listable(&'a dyn Listable), /// A Rust map value /// /// # Examples /// /// ``` /// use valuable::Value; /// use std::collections::HashMap; /// /// let mut map = HashMap::new(); /// map.insert("foo", 1); /// map.insert("bar", 2); /// /// let v = Value::Mappable(&map); /// ``` Mappable(&'a dyn Mappable), /// A Rust struct value /// /// # Examples /// /// ``` /// use valuable::{Value, Valuable}; /// /// #[derive(Valuable)] /// struct MyStruct { /// field: u32, /// } /// /// let my_struct = MyStruct { /// field: 123, /// }; /// /// let v = Value::Structable(&my_struct); /// ``` Structable(&'a dyn Structable), /// A Rust enum value /// /// # Examples /// /// ``` /// use valuable::{Value, Valuable}; /// /// #[derive(Valuable)] /// enum MyEnum { /// Foo, /// Bar, /// } /// /// let my_enum = MyEnum::Foo; /// let v = Value::Enumerable(&my_enum); /// ``` Enumerable(&'a dyn Enumerable), /// A tuple value /// /// # Examples /// /// ``` /// use valuable::{Value, Valuable}; /// /// let my_tuple = (123, 456); /// let v = Value::Tuplable(&my_tuple); /// ``` Tuplable(&'a dyn Tuplable), } impl Valuable for Value<'_> { fn as_value(&self) -> Value<'_> { *self } fn visit(&self, visit: &mut dyn Visit) { visit.visit_value(*self); } } impl Default for Value<'_> { fn default() -> Self { Value::Unit } } macro_rules! convert { ( $( $(#[$attrs:meta])* $ty:ty => $as:ident, )* ) => { impl<'a> Value<'a> { /// Return a `bool` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::Bool(true).as_bool(), Some(true)); /// assert_eq!(Value::Char('c').as_bool(), None); /// ``` pub fn as_bool(&self) -> Option { match *self { Value::Bool(v) => Some(v), _ => None, } } /// Return a `char` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::Char('c').as_char(), Some('c')); /// assert_eq!(Value::Bool(true).as_char(), None); /// ``` pub fn as_char(&self) -> Option { match *self { Value::Char(v) => Some(v), _ => None, } } /// Return a `f32` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::F32(3.1415).as_f32(), Some(3.1415)); /// assert_eq!(Value::Bool(true).as_f32(), None); /// ``` pub fn as_f32(&self) -> Option { match *self { Value::F32(v) => Some(v), _ => None, } } /// Return a `f64` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::F64(3.1415).as_f64(), Some(3.1415)); /// assert_eq!(Value::Bool(true).as_f64(), None); /// ``` pub fn as_f64(&self) -> Option { match *self { Value::F64(v) => Some(v), _ => None, } } $( $(#[$attrs])* pub fn $as(&self) -> Option<$ty> { use Value::*; use core::convert::TryInto; match *self { I8(v) => v.try_into().ok(), I16(v) => v.try_into().ok(), I32(v) => v.try_into().ok(), I64(v) => v.try_into().ok(), I128(v) => v.try_into().ok(), Isize(v) => v.try_into().ok(), U8(v) => v.try_into().ok(), U16(v) => v.try_into().ok(), U32(v) => v.try_into().ok(), U64(v) => v.try_into().ok(), U128(v) => v.try_into().ok(), Usize(v) => v.try_into().ok(), _ => None, } } )* /// Return a `&str` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::String("hello").as_str(), Some("hello")); /// assert_eq!(Value::Bool(true).as_str(), None); /// ``` pub fn as_str(&self) -> Option<&str> { match *self { Value::String(v) => Some(v), _ => None, } } /// Return a `&Path` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// use std::path::Path; /// /// let path = Path::new("a.txt"); /// /// assert!(Value::Path(path).as_path().is_some()); /// assert!(Value::Bool(true).as_path().is_none()); /// ``` #[cfg(feature = "std")] pub fn as_path(&self) -> Option<&std::path::Path> { match *self { Value::Path(v) => Some(v), _ => None, } } /// Return a `&dyn Error` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// use std::io; /// /// let err: io::Error = io::ErrorKind::Other.into(); /// /// assert!(Value::Error(&err).as_error().is_some()); /// assert!(Value::Bool(true).as_error().is_none()); /// ``` #[cfg(feature = "std")] pub fn as_error(&self) -> Option<&(dyn std::error::Error + 'static)> { match *self { Value::Error(v) => Some(v), _ => None, } } /// Return a `&dyn Listable` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let list = vec![1, 2, 3, 4]; /// /// assert!(Value::Listable(&list).as_listable().is_some()); /// assert!(Value::Bool(true).as_listable().is_none()); /// ``` pub fn as_listable(&self) -> Option<&dyn Listable> { match *self { Value::Listable(v) => Some(v), _ => None, } } /// Return a `&dyn Mappable` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// use std::collections::HashMap; /// /// let mut map = HashMap::new(); /// map.insert("foo", 123); /// map.insert("bar", 456); /// /// assert!(Value::Mappable(&map).as_mappable().is_some()); /// assert!(Value::Bool(true).as_mappable().is_none()); /// ``` pub fn as_mappable(&self) -> Option<&dyn Mappable> { match *self { Value::Mappable(v) => Some(v), _ => None, } } /// Return a `&dyn Structable` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::{Value, Valuable}; /// /// #[derive(Valuable)] /// struct Hello { /// message: &'static str, /// } /// /// let hello = Hello { message: "Hello world" }; /// /// assert!(Value::Structable(&hello).as_structable().is_some()); /// assert!(Value::Bool(true).as_structable().is_none()); /// ``` pub fn as_structable(&self) -> Option<&dyn Structable> { match *self { Value::Structable(v) => Some(v), _ => None, } } /// Return a `&dyn Enumerable` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::{Value, Valuable}; /// /// #[derive(Valuable)] /// enum Greet { /// Hello, /// World, /// } /// /// let greet = Greet::Hello; /// /// assert!(Value::Enumerable(&greet).as_enumerable().is_some()); /// assert!(Value::Bool(true).as_enumerable().is_none()); /// ``` pub fn as_enumerable(&self) -> Option<&dyn Enumerable> { match *self { Value::Enumerable(v) => Some(v), _ => None, } } /// Return a `&dyn Tuplable` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// let my_tuple = (123, 456); /// /// assert!(Value::Tuplable(&my_tuple).as_tuplable().is_some()); /// assert!(Value::Bool(true).as_tuplable().is_none()); /// ``` pub fn as_tuplable(&self) -> Option<&dyn Tuplable> { match *self { Value::Tuplable(v) => Some(v), _ => None, } } } } } convert! { /// Return a `i8` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::I8(42).as_i8(), Some(42)); /// assert_eq!(Value::I32(42).as_i8(), Some(42)); /// /// assert_eq!(Value::I64(i64::MAX).as_i8(), None); /// assert_eq!(Value::Bool(true).as_i8(), None); /// ``` i8 => as_i8, /// Return a `i16` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::I16(42).as_i16(), Some(42)); /// assert_eq!(Value::I32(42).as_i16(), Some(42)); /// /// assert_eq!(Value::I64(i64::MAX).as_i16(), None); /// assert_eq!(Value::Bool(true).as_i16(), None); /// ``` i16 => as_i16, /// Return a `i32` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::I32(42).as_i32(), Some(42)); /// assert_eq!(Value::I64(42).as_i32(), Some(42)); /// /// assert_eq!(Value::I64(i64::MAX).as_i32(), None); /// assert_eq!(Value::Bool(true).as_i32(), None); /// ``` i32 => as_i32, /// Return a `i64` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::I64(42).as_i64(), Some(42)); /// assert_eq!(Value::I128(42).as_i64(), Some(42)); /// /// assert_eq!(Value::I128(i128::MAX).as_i64(), None); /// assert_eq!(Value::Bool(true).as_i64(), None); /// ``` i64 => as_i64, /// Return a `i128` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::I128(42).as_i128(), Some(42)); /// assert_eq!(Value::U128(42).as_i128(), Some(42)); /// /// assert_eq!(Value::U128(u128::MAX).as_i128(), None); /// assert_eq!(Value::Bool(true).as_i128(), None); /// ``` i128 => as_i128, /// Return a `isize` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::Isize(42).as_isize(), Some(42)); /// assert_eq!(Value::Usize(42).as_isize(), Some(42)); /// /// assert_eq!(Value::Usize(usize::MAX).as_isize(), None); /// assert_eq!(Value::Bool(true).as_isize(), None); /// ``` isize => as_isize, /// Return a `u8` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::U8(42).as_u8(), Some(42)); /// assert_eq!(Value::U32(42).as_u8(), Some(42)); /// /// assert_eq!(Value::U32(u32::MAX).as_u8(), None); /// assert_eq!(Value::Bool(true).as_u8(), None); /// ``` u8 => as_u8, /// Return a `u16` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::U16(42).as_u16(), Some(42)); /// assert_eq!(Value::U32(42).as_u16(), Some(42)); /// /// assert_eq!(Value::U32(u32::MAX).as_u16(), None); /// assert_eq!(Value::Bool(true).as_u16(), None); /// ``` u16 => as_u16, /// Return a `u32` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::U32(42).as_u32(), Some(42)); /// assert_eq!(Value::U64(42).as_u32(), Some(42)); /// /// assert_eq!(Value::U64(u64::MAX).as_u32(), None); /// assert_eq!(Value::Bool(true).as_u32(), None); /// ``` u32 => as_u32, /// Return a `u64` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::U64(42).as_u64(), Some(42)); /// assert_eq!(Value::U128(42).as_u64(), Some(42)); /// /// assert_eq!(Value::U128(u128::MAX).as_u64(), None); /// assert_eq!(Value::Bool(true).as_u64(), None); /// ``` u64 => as_u64, /// Return a `u128` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::U128(42).as_u128(), Some(42)); /// assert_eq!(Value::I32(42).as_u128(), Some(42)); /// /// assert_eq!(Value::I32(-5).as_u128(), None); /// assert_eq!(Value::Bool(true).as_u128(), None); /// ``` u128 => as_u128, /// Return a `usize` representation of `self`, if possible. /// /// # Examples /// /// ``` /// use valuable::Value; /// /// assert_eq!(Value::Usize(42).as_usize(), Some(42)); /// assert_eq!(Value::I8(42).as_usize(), Some(42)); /// /// assert_eq!(Value::I8(-5).as_usize(), None); /// assert_eq!(Value::Bool(true).as_usize(), None); /// ``` usize => as_usize, }