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}