#[cfg(all(not(feature = "std"), not(test)))]
use alloc::{vec, vec::Vec};
use core::{cmp, fmt, iter};
#[cfg(any(feature = "std", test))]
use std::vec;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ThresholdError {
k: usize,
n: usize,
max: Option<usize>,
}
impl fmt::Display for ThresholdError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.n == 0 {
f.write_str("thresholds in Miniscript must be nonempty")
} else if self.k == 0 {
f.write_str("thresholds in Miniscript must have k > 0")
} else if self.k > self.n {
write!(f, "invalid threshold {}-of-{}; cannot have k > n", self.k, self.n)
} else {
debug_assert!(self.max.is_some());
let max = self.max.unwrap();
debug_assert!(self.n > max);
write!(f, "invalid threshold {}-of-{}; maximum size is {}", self.k, self.n, max)
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for ThresholdError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Threshold<T, const MAX: usize> {
k: usize,
inner: Vec<T>,
}
impl<T, const MAX: usize> Threshold<T, MAX> {
pub fn new(k: usize, inner: Vec<T>) -> Result<Self, ThresholdError> {
if k == 0 || k > inner.len() || (MAX > 0 && inner.len() > MAX) {
Err(ThresholdError { k, n: inner.len(), max: (MAX > 0).then(|| MAX) })
} else {
Ok(Threshold { k, inner })
}
}
pub fn from_iter<I: Iterator<Item = T>>(k: usize, iter: I) -> Result<Self, ThresholdError> {
let min_size = cmp::max(k, iter.size_hint().0);
if MAX > 0 && min_size > MAX {
let n = iter.count();
return Err(ThresholdError { k, n, max: (MAX > 0).then(|| MAX) });
}
let mut inner = Vec::with_capacity(min_size);
iter.for_each(|x| inner.push(x));
Self::new(k, inner)
}
pub fn or(left: T, right: T) -> Self {
debug_assert!(MAX == 0 || MAX > 1);
Threshold { k: 1, inner: vec![left, right] }
}
pub fn and(left: T, right: T) -> Self {
debug_assert!(MAX == 0 || MAX > 1);
Threshold { k: 2, inner: vec![left, right] }
}
pub fn is_or(&self) -> bool { self.k == 1 }
pub fn is_and(&self) -> bool { self.k == self.inner.len() }
pub fn set_maximum<const NEWMAX: usize>(self) -> Result<Threshold<T, NEWMAX>, ThresholdError> {
Threshold::new(self.k, self.inner)
}
pub fn forget_maximum(self) -> Threshold<T, 0> { Threshold { k: self.k, inner: self.inner } }
pub fn map<U, F: FnMut(T) -> U>(self, mapfn: F) -> Threshold<U, MAX> {
Threshold { k: self.k, inner: self.inner.into_iter().map(mapfn).collect() }
}
pub fn map_ref<U, F: FnMut(&T) -> U>(&self, mapfn: F) -> Threshold<U, MAX> {
Threshold { k: self.k, inner: self.inner.iter().map(mapfn).collect() }
}
pub fn translate<U, F, FuncError>(self, translatefn: F) -> Result<Threshold<U, MAX>, FuncError>
where
F: FnMut(T) -> Result<U, FuncError>,
{
let k = self.k;
self.inner
.into_iter()
.map(translatefn)
.collect::<Result<Vec<_>, _>>()
.map(|inner| Threshold { k, inner })
}
pub fn translate_ref<U, F, FuncError>(
&self,
translatefn: F,
) -> Result<Threshold<U, MAX>, FuncError>
where
F: FnMut(&T) -> Result<U, FuncError>,
{
let k = self.k;
self.inner
.iter()
.map(translatefn)
.collect::<Result<Vec<_>, _>>()
.map(|inner| Threshold { k, inner })
}
pub fn translate_by_index<U, F, FuncError>(
&self,
translatefn: F,
) -> Result<Threshold<U, MAX>, FuncError>
where
F: FnMut(usize) -> Result<U, FuncError>,
{
let k = self.k;
(0..self.inner.len())
.map(translatefn)
.collect::<Result<Vec<_>, _>>()
.map(|inner| Threshold { k, inner })
}
pub fn map_from_post_order_iter<U: Clone>(
&self,
child_indices: &[usize],
processed: &[U],
) -> Threshold<U, MAX> {
debug_assert_eq!(
self.inner.len(),
child_indices.len(),
"internal consistency error translating threshold by post-order iterator"
);
let mut processed_inner = Vec::with_capacity(self.inner.len());
processed_inner.extend(child_indices.iter().copied().map(|n| processed[n].clone()));
Threshold { k: self.k, inner: processed_inner }
}
pub fn n(&self) -> usize { self.inner.len() }
pub const fn k(&self) -> usize { self.k }
pub fn data(&self) -> &[T] { &self.inner }
pub fn data_mut(&mut self) -> &mut [T] { &mut self.inner }
pub fn into_data(self) -> Vec<T> { self.inner }
pub fn iter(&self) -> core::slice::Iter<T> { self.inner.iter() }
}
impl<T> Threshold<T, 0> {
pub fn or_n(inner: Vec<T>) -> Self {
assert_ne!(inner.len(), 0);
Threshold { k: 1, inner }
}
pub fn and_n(inner: Vec<T>) -> Self {
assert_ne!(inner.len(), 0);
Threshold { k: inner.len(), inner }
}
}
impl<T, const MAX: usize> iter::IntoIterator for Threshold<T, MAX> {
type Item = T;
type IntoIter = vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter { self.inner.into_iter() }
}
impl<T: fmt::Display, const MAX: usize> Threshold<T, MAX> {
pub fn display<'s>(&'s self, name: &'s str, show_k: bool) -> impl fmt::Display + 's {
ThreshDisplay { name, thresh: self, show_k }
}
}
impl<T: fmt::Debug, const MAX: usize> Threshold<T, MAX> {
pub fn debug<'s>(&'s self, name: &'s str, show_k: bool) -> impl fmt::Debug + 's {
ThreshDisplay { name, thresh: self, show_k }
}
}
struct ThreshDisplay<'t, 's, T, const MAX: usize> {
name: &'s str,
thresh: &'t Threshold<T, MAX>,
show_k: bool,
}
impl<'t, 's, T, const MAX: usize> fmt::Display for ThreshDisplay<'t, 's, T, MAX>
where
T: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use core::fmt::Write;
f.write_str(self.name)?;
f.write_char('(')?;
let inners = if self.show_k {
write!(f, "{}", self.thresh.k)?;
&self.thresh.inner[0..]
} else {
write!(f, "{}", self.thresh.inner[0])?;
&self.thresh.inner[1..]
};
for inner in inners {
write!(f, ",{}", inner)?;
}
f.write_char(')')
}
}
impl<'t, 's, T, const MAX: usize> fmt::Debug for ThreshDisplay<'t, 's, T, MAX>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use core::fmt::Write;
f.write_str(self.name)?;
f.write_char('(')?;
let inners = if self.show_k {
write!(f, "{}", self.thresh.k)?;
&self.thresh.inner[0..]
} else {
write!(f, "{:?}", self.thresh.inner[0])?;
&self.thresh.inner[1..]
};
for inner in inners {
write!(f, ",{:?}", inner)?;
}
f.write_char(')')
}
}