1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use crate::{Value, ValueResult};

/// A trait to allow "extension" of the [`Value`] enum.
///
/// Sometimes, the basic types supported by `Value` are not enough and the newtype pattern is required to extend it.
/// Registering this newtype as `Valueable` means that it supports all common operations associated with a `Value`.
///
/// Besides implementing the required methods. Any type that implements [`Valueable`] is required to implement the following traits: 
/// * [`std::fmt::Debug`]
/// * [`std::fmt::Display`]
/// * [`Clone`]
/// * [`Eq`]
/// * [`PartialEq`]
/// * [`PartialOrd`]
/// * [`std::hash::Hash`]
/// * [`std::ops::Add`]
/// * [`std::ops::Sub`]
/// * [`std::ops::Mul`]
/// * [`std::ops::Div`]
/// * [`std::ops::Rem`]
/// * [`num_traits::Pow<Self>`]
/// This is required such that we can expect any `Valueable` type to work more or less the same.
///
/// Most of the required traits can be automatically derived. You can use [`wagon_macros::ValueOps`] (or it's associated methods) to 
/// automatically derive implementations for all the operative traits (`Add`, `Sub`, etc).
pub trait Valueable: 
    std::fmt::Debug 
    + std::fmt::Display 
    + Clone
    + Eq 
    + PartialEq 
    + PartialOrd
    + std::hash::Hash 
    + std::ops::Add
    + std::ops::Sub
    + std::ops::Mul
    + std::ops::Div
    + std::ops::Rem
    + num_traits::Pow<Self> 
    {
    /// Is this value seen as `true` or `false`?
    ///
    /// # Errors
    /// Should return an error if this value can not be converted into a `bool`.
    fn is_truthy(&self) -> ValueResult<bool, Self>;
    /// Convert the value to a regular [`i32`].
    ///
    /// # Errors
    /// Should return an error if this value can not be converted into an `i32`.
    fn to_int(&self) -> ValueResult<i32, Self>;
    /// Convert the value to a regular [`f32`].
    ///
    /// # Errors
    /// Should return an error if this value can not be converted into an `f32`.
    fn to_float(&self) -> ValueResult<f32, Self>;
    /// Get a string representation of the value, as if it were a number. 
    ///
    /// # Errors
    /// Should return an error if this value can not be displayed as a number
    fn display_numerical(&self) -> ValueResult<String, Self>;
}

/// A second trait for "extension" of the [`Value`] enum.
///
/// This is intended to "extract" the inner value if possible and makes automatic implementation
/// of [`Valueable`] possible. 
/// If your type properly wraps [`Value`] (as in, it implements [`ToValue`], [`From<Value<Self>>`] and all the expected operations),
/// [`Valueable`] is automatically implemented by simply taking the value returned by [`ToValue::to_value`] and using that implementation. 
/// If you do not desire this behaviour, do not implement [`ToValue`].
pub trait ToValue<T: Valueable> {
    /// Return a reference to the [`Value`] that this type encompasses.
    fn to_value(&self) -> &Value<T>;
}

impl<T: 
    ToValue<T> 
    + From<Value<T>> 
    + Clone
    + Eq 
    + PartialEq 
    + PartialOrd
    + std::fmt::Debug 
    + std::fmt::Display 
    + std::hash::Hash 
    + std::ops::Add
    + std::ops::Sub
    + std::ops::Mul
    + std::ops::Div
    + std::ops::Rem
    + num_traits::Pow<T>> 
    Valueable for T {
    fn is_truthy(&self) -> ValueResult<bool, Self> {
        Ok(self.to_value().is_truthy()?)
    }

    fn to_int(&self) -> ValueResult<i32, Self> {
        Ok(self.to_value().to_int()?)
    }

    fn to_float(&self) -> ValueResult<f32, Self> {
        Ok(self.to_value().to_float()?)
    }

    fn display_numerical(&self) -> ValueResult<String, Self> {
        Ok(self.to_value().display_numerical()?)
    }
}