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}