1use super::util::{address_of_slice, count_slice_allocations};
18use std::collections::BTreeMap;
19
20pub type Ballot = BallotImpl<BoxedFlatOrder>;
22
23#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct BallotImpl<O: Order + Clone> {
26 count: usize,
28 has_tie: bool,
30 order: O,
32}
33
34impl<O: Order + Clone> BallotImpl<O> {
35 #[inline(always)]
37 pub fn new(
38 count: usize,
39 order: impl IntoIterator<Item = impl IntoIterator<Item = usize>>,
40 ) -> Self {
41 let order = O::new(order);
42 let has_tie = order.order().any(|ranking| ranking.len() != 1);
43 Self {
44 count,
45 has_tie,
46 order,
47 }
48 }
49
50 #[cfg(test)]
52 pub(crate) fn empty() -> Self {
53 Self {
54 count: 0,
55 has_tie: false,
56 order: O::empty(),
57 }
58 }
59
60 #[cfg(test)]
62 pub(crate) fn empties(count: usize) -> Self {
63 Self {
64 count,
65 has_tie: false,
66 order: O::empty(),
67 }
68 }
69
70 #[inline(always)]
72 pub fn count(&self) -> usize {
73 self.count
74 }
75
76 #[inline(always)]
80 pub fn order(&self) -> impl Iterator<Item = &[impl Into<usize> + Copy + '_]> + '_ {
81 self.order.order()
82 }
83
84 #[inline(always)]
86 pub fn is_empty(&self) -> bool {
87 self.order.is_empty()
88 }
89
90 #[inline(always)]
92 pub(crate) fn order_len(&self) -> usize {
93 self.order.len()
94 }
95
96 #[inline(always)]
98 pub(crate) fn order_at(&self, i: usize) -> &[impl Into<usize> + Copy + '_] {
99 self.order.at(i)
100 }
101
102 #[inline(always)]
104 pub fn has_tie(&self) -> bool {
105 self.has_tie
106 }
107
108 pub fn validate(&self) {
111 assert!(self.count() > 0);
112 let mut all: Vec<usize> = self.candidates().map(|&x| x.into()).collect();
113 all.sort_unstable();
114 let len = all.len();
115 all.dedup();
116 assert_eq!(len, all.len());
117 }
118
119 #[inline(always)]
121 fn candidates(&self) -> impl Iterator<Item = &(impl Into<usize> + Copy + '_)> + '_ {
122 self.order.candidates()
123 }
124
125 #[inline(always)]
126 pub(super) fn count_allocations(&self, allocations: &mut BTreeMap<usize, usize>) {
127 self.order.count_allocations(allocations)
128 }
129
130 #[inline(always)]
131 pub(super) fn allocated_addresses(&self) -> impl Iterator<Item = usize> + '_ {
132 self.order.allocated_addresses()
133 }
134}
135
136pub trait Order {
138 fn new(order: impl IntoIterator<Item = impl IntoIterator<Item = usize>>) -> Self;
140
141 #[cfg(test)]
143 fn empty() -> Self;
144
145 fn order(&self) -> impl Iterator<Item = &[impl Into<usize> + Copy]>;
148
149 fn len(&self) -> usize;
151
152 fn is_empty(&self) -> bool;
154
155 fn at(&self, i: usize) -> &[impl Into<usize> + Copy];
157
158 fn candidates(&self) -> impl Iterator<Item = &(impl Into<usize> + Copy)>;
161
162 fn count_allocations(&self, allocations: &mut BTreeMap<usize, usize>);
165
166 fn allocated_addresses(&self) -> impl Iterator<Item = usize>;
168}
169
170#[derive(Debug, Clone, PartialEq, Eq)]
172pub struct BoxedFlatOrder {
173 order: Box<[u8]>,
175 order_indices: Box<[u8]>,
177}
178
179impl Order for BoxedFlatOrder {
180 fn new(into_order: impl IntoIterator<Item = impl IntoIterator<Item = usize>>) -> Self {
181 let mut order = Vec::new();
182 let mut order_indices = vec![0];
183 for rank in into_order.into_iter() {
184 for x in rank.into_iter() {
185 order.push(x.try_into().unwrap());
186 }
187 order_indices.push(order.len().try_into().unwrap());
188 }
189
190 if order.is_empty() {
191 order_indices = Vec::new();
192 }
193
194 Self {
195 order: order.into_boxed_slice(),
196 order_indices: order_indices.into_boxed_slice(),
197 }
198 }
199
200 #[cfg(test)]
201 fn empty() -> Self {
202 Self {
203 order: Box::new([]),
204 order_indices: Box::new([]),
205 }
206 }
207
208 #[inline(always)]
209 fn order(&self) -> impl Iterator<Item = &[impl Into<usize> + Copy]> {
210 let count = if self.order_indices.is_empty() {
212 0
213 } else {
214 self.order_indices.len() - 1
215 };
216 (0..count).map(|i| {
217 let start = self.order_indices[i];
218 let end = self.order_indices[i + 1];
219 &self.order[start.into()..end.into()]
220 })
221 }
222
223 #[inline(always)]
224 fn len(&self) -> usize {
225 self.order_indices.len() - 1
226 }
227
228 #[inline(always)]
229 fn is_empty(&self) -> bool {
230 self.order_indices.is_empty()
231 }
232
233 #[inline(always)]
234 fn at(&self, i: usize) -> &[impl Into<usize> + Copy] {
235 let start = self.order_indices[i];
236 let end = self.order_indices[i + 1];
237 &self.order[start.into()..end.into()]
238 }
239
240 #[inline(always)]
241 fn candidates(&self) -> impl Iterator<Item = &(impl Into<usize> + Copy)> {
242 self.order.iter()
243 }
244
245 #[inline(always)]
246 fn count_allocations(&self, allocations: &mut BTreeMap<usize, usize>) {
247 count_slice_allocations(allocations, &self.order);
248 count_slice_allocations(allocations, &self.order_indices);
249 }
250
251 #[inline(always)]
252 fn allocated_addresses(&self) -> impl Iterator<Item = usize> {
253 [
254 address_of_slice(&self.order),
255 address_of_slice(&self.order_indices),
256 ]
257 .into_iter()
258 .flatten()
259 }
260}