Skip to main content

weighted_list/
weighted_item.rs

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