weighted_list/
weighted_item.rs

1use std::{
2    fmt
3};
4
5use crate::root::*;
6
7
8/// A shorthand for [`WeightedItem`].
9/// 
10/// If you refer to [`WeightedItem`] prolifically in your code, you may wish to use this for brevity. Otherwise, the full [`WeightedItem`] is recommended for clarity.
11pub type WItem<V,W> = WeightedItem<V,W>;
12
13
14/// An item in a [`WeightedList`](crate::WeightedList), with a `value` of type `V` and a `weight` of numerical type `W`.
15/// 
16/// For consistency and layout, `weight` always comes before `value` when ordering is relevant. Methods and conversions will expect `(W, V)`, not `(V, W)`.
17/// 
18/// You should rarely find yourself constructing a [`WeightedItem`] by hand – instead, you'll usually interact with existing instances from a [`WeightedList`](crate::WeightedList).
19#[derive(Clone, Hash, PartialEq, Eq, Debug)]
20pub struct WeightedItem<V, W: Weight>
21{
22    /// The weight of the item. A positive number. `0` is technically valid, but not advised.
23    /// 
24    /// # Notes
25    /// 
26    /// - `num_traits::Unsigned` is not enforced because this is incompatible with non-integer `W` (`f32`, `f64`, etc.) which are always signed.
27    pub weight: W,
28
29    /// The value stored in the item.
30    pub value: V,
31}
32
33// == CONSTRUCTORS == //
34impl<V, W: Weight> WeightedItem<V,W>
35{
36    /// Construct an item with `value` and a weight of `1`.
37    pub fn unit(value: V) -> Self
38    {
39        Self {
40            weight: W::one(),
41            value
42        }
43    }
44
45    /// Construct an item with `value` and `weight`.
46    pub fn new(weight: W, value: V) -> Self
47    {
48        Self { weight, value }
49    }
50
51    /// Construct an item from a `(weight, value)` pair.
52    pub fn from((weight, value): (W, V)) -> Self
53    {
54        Self { weight, value }
55    }
56}
57
58/// Construct a [`WeightedItem`] from a `(weight, value)` pair.
59/// 
60/// # Usage
61/// 
62/// ```
63/// # use weighted_list::*;
64/// let item = wit!(2.0, "sup");
65/// assert_eq!(item, WeightedItem::new(2.0, "sup"));
66/// ```
67#[macro_export]
68macro_rules! wit {
69    ($weight: expr, $value: expr) => {
70        WeightedItem::new($weight, $value)
71    };
72}
73
74// == CONVERSIONS == //
75impl<V, W: Weight> From<WeightedItem<V,W>> for (W, V)
76{
77    fn from(item: WeightedItem<V,W>) -> Self {
78        (item.weight, item.value)
79    }
80}
81
82// == TRAIT IMPLEMENTATIONS == //
83impl<V, W: Weight> Ord for WeightedItem<V,W>
84    where
85        V: Eq,
86        W: Ord,
87{
88    fn cmp(&self, other: &Self) -> std::cmp::Ordering
89    {
90        self.weight.cmp(&other.weight)
91            // .then(self.value.cmp(&other.value))  // TODO FIXME
92    }
93}
94
95impl<V, W: Weight> PartialOrd for WeightedItem<V,W>
96    where
97        V: Eq,
98{
99    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering>
100    {
101        self.weight.partial_cmp(&other.weight)
102    }
103}
104
105impl<V, W: Weight> Default for WeightedItem<V,W>
106    where
107        V: Default,
108        W: Default,
109{
110    fn default() -> Self {
111        Self { weight: W::default(), value: V::default() }
112    }
113}
114
115impl<V, W: Weight> fmt::Display for WeightedItem<V,W>
116    where
117        V: fmt::Display,
118        W: fmt::Display,
119{
120    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
121    {
122        write!(f, "{{ {}, {} }}", self.weight, self.value)
123    }
124}