mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 09:21:04 +00:00
Decouple Stkaing and Election - Part1: Support traits (#7908)
* Base features and traits. * Fix the build * Remove unused boxing * Self review cleanup * Fix build
This commit is contained in:
@@ -21,7 +21,7 @@ use crate::field_name_for;
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
|
||||
fn from_impl(count: usize) -> TokenStream2 {
|
||||
pub(crate) fn from_impl(count: usize) -> TokenStream2 {
|
||||
let from_impl_single = {
|
||||
let name = field_name_for(1);
|
||||
quote!(1 => compact.#name.push(
|
||||
@@ -73,7 +73,7 @@ fn from_impl(count: usize) -> TokenStream2 {
|
||||
)
|
||||
}
|
||||
|
||||
fn into_impl(count: usize, per_thing: syn::Type) -> TokenStream2 {
|
||||
pub(crate) fn into_impl(count: usize, per_thing: syn::Type) -> TokenStream2 {
|
||||
let into_impl_single = {
|
||||
let name = field_name_for(1);
|
||||
quote!(
|
||||
@@ -153,53 +153,3 @@ fn into_impl(count: usize, per_thing: syn::Type) -> TokenStream2 {
|
||||
#into_impl_rest
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn assignment(
|
||||
ident: syn::Ident,
|
||||
voter_type: syn::Type,
|
||||
target_type: syn::Type,
|
||||
weight_type: syn::Type,
|
||||
count: usize,
|
||||
) -> TokenStream2 {
|
||||
let from_impl = from_impl(count);
|
||||
let into_impl = into_impl(count, weight_type.clone());
|
||||
|
||||
quote!(
|
||||
use _npos::__OrInvalidIndex;
|
||||
impl #ident {
|
||||
pub fn from_assignment<FV, FT, A>(
|
||||
assignments: Vec<_npos::Assignment<A, #weight_type>>,
|
||||
index_of_voter: FV,
|
||||
index_of_target: FT,
|
||||
) -> Result<Self, _npos::Error>
|
||||
where
|
||||
A: _npos::IdentifierT,
|
||||
for<'r> FV: Fn(&'r A) -> Option<#voter_type>,
|
||||
for<'r> FT: Fn(&'r A) -> Option<#target_type>,
|
||||
{
|
||||
let mut compact: #ident = Default::default();
|
||||
|
||||
for _npos::Assignment { who, distribution } in assignments {
|
||||
match distribution.len() {
|
||||
0 => continue,
|
||||
#from_impl
|
||||
_ => {
|
||||
return Err(_npos::Error::CompactTargetOverflow);
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(compact)
|
||||
}
|
||||
|
||||
pub fn into_assignment<A: _npos::IdentifierT>(
|
||||
self,
|
||||
voter_at: impl Fn(#voter_type) -> Option<A>,
|
||||
target_at: impl Fn(#target_type) -> Option<A>,
|
||||
) -> Result<Vec<_npos::Assignment<A, #weight_type>>, _npos::Error> {
|
||||
let mut assignments: Vec<_npos::Assignment<A, #weight_type>> = Default::default();
|
||||
#into_impl
|
||||
Ok(assignments)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -95,19 +95,11 @@ pub fn generate_solution_type(item: TokenStream) -> TokenStream {
|
||||
compact_encoding,
|
||||
).unwrap_or_else(|e| e.to_compile_error());
|
||||
|
||||
let assignment_impls = assignment::assignment(
|
||||
ident.clone(),
|
||||
voter_type.clone(),
|
||||
target_type.clone(),
|
||||
weight_type.clone(),
|
||||
count,
|
||||
);
|
||||
|
||||
quote!(
|
||||
#imports
|
||||
#solution_struct
|
||||
#assignment_impls
|
||||
).into()
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn struct_def(
|
||||
@@ -125,29 +117,32 @@ fn struct_def(
|
||||
|
||||
let singles = {
|
||||
let name = field_name_for(1);
|
||||
// NOTE: we use the visibility of the struct for the fields as well.. could be made better.
|
||||
quote!(
|
||||
#name: Vec<(#voter_type, #target_type)>,
|
||||
#vis #name: Vec<(#voter_type, #target_type)>,
|
||||
)
|
||||
};
|
||||
|
||||
let doubles = {
|
||||
let name = field_name_for(2);
|
||||
quote!(
|
||||
#name: Vec<(#voter_type, (#target_type, #weight_type), #target_type)>,
|
||||
#vis #name: Vec<(#voter_type, (#target_type, #weight_type), #target_type)>,
|
||||
)
|
||||
};
|
||||
|
||||
let rest = (3..=count).map(|c| {
|
||||
let field_name = field_name_for(c);
|
||||
let array_len = c - 1;
|
||||
quote!(
|
||||
#field_name: Vec<(
|
||||
#voter_type,
|
||||
[(#target_type, #weight_type); #array_len],
|
||||
#target_type
|
||||
)>,
|
||||
)
|
||||
}).collect::<TokenStream2>();
|
||||
let rest = (3..=count)
|
||||
.map(|c| {
|
||||
let field_name = field_name_for(c);
|
||||
let array_len = c - 1;
|
||||
quote!(
|
||||
#vis #field_name: Vec<(
|
||||
#voter_type,
|
||||
[(#target_type, #weight_type); #array_len],
|
||||
#target_type
|
||||
)>,
|
||||
)
|
||||
})
|
||||
.collect::<TokenStream2>();
|
||||
|
||||
let len_impl = len_impl(count);
|
||||
let edge_count_impl = edge_count_impl(count);
|
||||
@@ -172,40 +167,38 @@ fn struct_def(
|
||||
quote!(#[derive(Default, PartialEq, Eq, Clone, Debug, _npos::codec::Encode, _npos::codec::Decode)])
|
||||
};
|
||||
|
||||
let from_impl = assignment::from_impl(count);
|
||||
let into_impl = assignment::into_impl(count, weight_type.clone());
|
||||
|
||||
Ok(quote! (
|
||||
/// A struct to encode a election assignment in a compact way.
|
||||
#derives_and_maybe_compact_encoding
|
||||
#vis struct #ident { #singles #doubles #rest }
|
||||
|
||||
impl _npos::VotingLimit for #ident {
|
||||
use _npos::__OrInvalidIndex;
|
||||
impl _npos::CompactSolution for #ident {
|
||||
const LIMIT: usize = #count;
|
||||
}
|
||||
type Voter = #voter_type;
|
||||
type Target = #target_type;
|
||||
type Accuracy = #weight_type;
|
||||
|
||||
impl #ident {
|
||||
/// Get the length of all the assignments that this type is encoding. This is basically
|
||||
/// the same as the number of assignments, or the number of voters in total.
|
||||
pub fn len(&self) -> usize {
|
||||
fn voter_count(&self) -> usize {
|
||||
let mut all_len = 0usize;
|
||||
#len_impl
|
||||
all_len
|
||||
}
|
||||
|
||||
/// Get the total count of edges.
|
||||
pub fn edge_count(&self) -> usize {
|
||||
fn edge_count(&self) -> usize {
|
||||
let mut all_edges = 0usize;
|
||||
#edge_count_impl
|
||||
all_edges
|
||||
}
|
||||
|
||||
/// Get the number of unique targets in the whole struct.
|
||||
///
|
||||
/// Once presented with a list of winners, this set and the set of winners must be
|
||||
/// equal.
|
||||
///
|
||||
/// The resulting indices are sorted.
|
||||
pub fn unique_targets(&self) -> Vec<#target_type> {
|
||||
let mut all_targets: Vec<#target_type> = Vec::with_capacity(self.average_edge_count());
|
||||
let mut maybe_insert_target = |t: #target_type| {
|
||||
fn unique_targets(&self) -> Vec<Self::Target> {
|
||||
// NOTE: this implementation returns the targets sorted, but we don't use it yet per
|
||||
// se, nor is the API enforcing it.
|
||||
let mut all_targets: Vec<Self::Target> = Vec::with_capacity(self.average_edge_count());
|
||||
let mut maybe_insert_target = |t: Self::Target| {
|
||||
match all_targets.binary_search(&t) {
|
||||
Ok(_) => (),
|
||||
Err(pos) => all_targets.insert(pos, t)
|
||||
@@ -217,22 +210,44 @@ fn struct_def(
|
||||
all_targets
|
||||
}
|
||||
|
||||
/// Get the average edge count.
|
||||
pub fn average_edge_count(&self) -> usize {
|
||||
self.edge_count().checked_div(self.len()).unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Remove a certain voter.
|
||||
///
|
||||
/// This will only search until the first instance of `to_remove`, and return true. If
|
||||
/// no instance is found (no-op), then it returns false.
|
||||
///
|
||||
/// In other words, if this return true, exactly one element must have been removed from
|
||||
/// `self.len()`.
|
||||
pub fn remove_voter(&mut self, to_remove: #voter_type) -> bool {
|
||||
fn remove_voter(&mut self, to_remove: Self::Voter) -> bool {
|
||||
#remove_voter_impl
|
||||
return false
|
||||
}
|
||||
|
||||
fn from_assignment<FV, FT, A>(
|
||||
assignments: Vec<_npos::Assignment<A, #weight_type>>,
|
||||
index_of_voter: FV,
|
||||
index_of_target: FT,
|
||||
) -> Result<Self, _npos::Error>
|
||||
where
|
||||
A: _npos::IdentifierT,
|
||||
for<'r> FV: Fn(&'r A) -> Option<Self::Voter>,
|
||||
for<'r> FT: Fn(&'r A) -> Option<Self::Target>,
|
||||
{
|
||||
let mut compact: #ident = Default::default();
|
||||
|
||||
for _npos::Assignment { who, distribution } in assignments {
|
||||
match distribution.len() {
|
||||
0 => continue,
|
||||
#from_impl
|
||||
_ => {
|
||||
return Err(_npos::Error::CompactTargetOverflow);
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(compact)
|
||||
}
|
||||
|
||||
fn into_assignment<A: _npos::IdentifierT>(
|
||||
self,
|
||||
voter_at: impl Fn(Self::Voter) -> Option<A>,
|
||||
target_at: impl Fn(Self::Target) -> Option<A>,
|
||||
) -> Result<Vec<_npos::Assignment<A, #weight_type>>, _npos::Error> {
|
||||
let mut assignments: Vec<_npos::Assignment<A, #weight_type>> = Default::default();
|
||||
#into_impl
|
||||
Ok(assignments)
|
||||
}
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user