use crate::core_crypto::commons::numeric::CastInto;
use std::marker::PhantomData;
pub trait ParameterSetConformant {
type ParameterSet;
fn is_conformant(&self, parameter_set: &Self::ParameterSet) -> bool;
}
#[derive(Copy, Clone)]
pub struct ListSizeConstraint {
min_inclusive_group_count: usize,
max_inclusive_group_count: usize,
group_size: usize,
}
impl ListSizeConstraint {
pub fn exact_size(size: usize) -> Self {
Self {
min_inclusive_group_count: size,
max_inclusive_group_count: size,
group_size: 1,
}
}
pub fn try_size_in_range(min_inclusive: usize, max_inclusive: usize) -> Result<Self, String> {
if max_inclusive < min_inclusive {
return Err("max_inclusive < min_inclusive".to_owned());
}
Ok(Self {
min_inclusive_group_count: min_inclusive,
max_inclusive_group_count: max_inclusive,
group_size: 1,
})
}
pub fn try_size_of_group_in_range(
group_size: usize,
min_inclusive_group_count: usize,
max_inclusive_group_count: usize,
) -> Result<Self, String> {
if max_inclusive_group_count < min_inclusive_group_count {
return Err("max_inclusive < min_inclusive".to_owned());
}
Ok(Self {
min_inclusive_group_count,
max_inclusive_group_count,
group_size,
})
}
pub fn multiply_group_size(&self, group_size_multiplier: usize) -> Self {
Self {
min_inclusive_group_count: self.min_inclusive_group_count,
max_inclusive_group_count: self.max_inclusive_group_count,
group_size: self.group_size * group_size_multiplier,
}
}
pub fn is_valid(&self, size: usize) -> bool {
if self.group_size == 0 {
size == 0
} else {
size.is_multiple_of(self.group_size)
&& size >= self.min_inclusive_group_count * self.group_size
&& size <= self.max_inclusive_group_count * self.group_size
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct EnumSet<T> {
mask: u128,
_phantom: PhantomData<T>,
}
impl<T> Default for EnumSet<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> EnumSet<T> {
pub const fn new() -> Self {
Self {
mask: 0,
_phantom: PhantomData,
}
}
}
impl<T> EnumSet<T>
where
T: CastInto<usize> + Copy,
{
pub fn contains(&self, value: T) -> bool
where
T: std::fmt::Debug,
{
let index = value.cast_into();
if index < 128 {
(self.mask & (1 << index)) != 0
} else {
false
}
}
pub fn insert(&mut self, value: T) {
let index = value.cast_into();
assert!(index < 128, "Config index too large for u128");
self.mask |= 1 << index;
}
pub fn remove(&mut self, value: T) {
let index = value.cast_into();
if index < 128 {
self.mask &= !(1 << index);
}
}
}