1use super::*;
21use core::{
22 marker::PhantomData,
23 ops::{Div, Rem},
24};
25
26#[derive(
30 CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, DebugNoBound, TypeInfo, MaxEncodedLen,
31)]
32#[scale_info(skip_type_params(MaxEntries))]
33pub struct Bitfield<MaxEntries: Get<u32>>(pub BoundedVec<u16, BitfieldLenOf<MaxEntries>>);
34
35pub type BitfieldLenOf<MaxEntries> = ConstDivCeil<MaxEntries, ConstU32<16>, u32, u32>;
37
38pub struct ConstDivCeil<Dividend, Divisor, R, T>(pub PhantomData<(Dividend, Divisor, R, T)>);
40
41impl<Dividend: Get<T>, Divisor: Get<T>, R: AtLeast32BitUnsigned, T: Into<R>> Get<R>
42 for ConstDivCeil<Dividend, Divisor, R, T>
43where
44 R: Div + Rem + Zero + One + Copy,
45{
46 fn get() -> R {
47 let dividend: R = Dividend::get().into();
48 let divisor: R = Divisor::get().into();
49
50 let v = dividend / divisor;
51 let remainder = dividend % divisor;
52
53 if remainder.is_zero() {
54 v
55 } else {
56 v + One::one()
57 }
58 }
59}
60
61impl<MaxEntries: Get<u32>> Default for Bitfield<MaxEntries> {
62 fn default() -> Self {
63 Self(
64 vec![0u16; BitfieldLenOf::<MaxEntries>::get() as usize]
65 .try_into()
66 .expect("Bitfield construction checked in integrity test; qed."),
67 )
68 }
69}
70
71impl<MaxEntries: Get<u32>> Bitfield<MaxEntries> {
72 pub fn set_if_not_set(&mut self, index: usize) -> Result<(), ()> {
74 let word_index = index / 16;
75 let bit_index = index % 16;
76
77 let word = self.0.get_mut(word_index).ok_or(())?;
78 if (*word & (1u16 << bit_index)) == 0 {
79 *word |= 1u16 << bit_index;
80 Ok(())
81 } else {
82 Err(())
83 }
84 }
85
86 pub fn with_bits(mut self, indices: impl IntoIterator<Item = usize>) -> Result<Self, ()> {
90 for index in indices {
91 self.set_if_not_set(index)?;
92 }
93 Ok(self)
94 }
95
96 pub fn count_ones(&self) -> u32 {
98 self.0.iter().cloned().map(u16::count_ones).sum()
99 }
100
101 pub fn iter_ones(&self) -> impl Iterator<Item = usize> + '_ {
103 self.0.iter().enumerate().flat_map(|(word_index, word)| {
104 (0..16usize).filter_map(move |bit_index| {
105 ((word & (1u16 << bit_index)) != 0).then_some(word_index * 16 + bit_index)
106 })
107 })
108 }
109}
110
111#[derive(
118 Clone,
119 Eq,
120 PartialEq,
121 Encode,
122 Decode,
123 Default,
124 Debug,
125 TypeInfo,
126 MaxEncodedLen,
127 DecodeWithMemTracking,
128)]
129pub struct IdentifiedConsideration<AccountId, Footprint, C> {
130 pub depositor: AccountId,
134
135 pub ticket: Option<C>,
137
138 #[doc(hidden)]
139 pub _phantom: PhantomData<Footprint>,
140}
141
142impl<AccountId: Clone + Eq, Footprint, C: Consideration<AccountId, Footprint>>
143 IdentifiedConsideration<AccountId, Footprint, C>
144{
145 pub fn new(
147 depositor: &AccountId,
148 fp: impl Into<Option<Footprint>>,
149 ) -> Result<Self, DispatchError> {
150 let ticket = if let Some(fp) = fp.into() {
151 Some(Consideration::<AccountId, Footprint>::new(depositor, fp)?)
152 } else {
153 None
154 };
155
156 Ok(Self { depositor: depositor.clone(), ticket, _phantom: Default::default() })
157 }
158
159 pub fn update(
161 self,
162 new_depositor: &AccountId,
163 new_fp: impl Into<Option<Footprint>>,
164 ) -> Result<Self, DispatchError> {
165 let fp = new_fp.into();
166 if let Some(ticket) = self.ticket {
167 ticket.drop(&self.depositor)?;
168 }
169
170 let ticket = if let Some(fp) = fp {
171 Some(Consideration::<AccountId, Footprint>::new(&new_depositor, fp)?)
172 } else {
173 None
174 };
175 Ok(Self { depositor: new_depositor.clone(), ticket, _phantom: Default::default() })
176 }
177
178 pub fn try_drop(self) -> Result<(), DispatchError> {
180 if let Some(ticket) = self.ticket {
181 ticket.drop(&self.depositor)?;
182 }
183 Ok(())
184 }
185}