use crate::FusedError;
use std::{
borrow::{Borrow, BorrowMut},
fmt::{self, Debug, Display},
ops::{Deref, DerefMut, Index, IndexMut},
slice::SliceIndex,
};
#[derive(Clone, Eq, PartialOrd, Ord, Hash)]
pub struct Accumulated<E> {
inner: Vec<E>,
}
impl<E> Accumulated<E> {
#[must_use]
#[inline]
pub fn new() -> Self {
Accumulated::from_vec(Vec::new())
}
#[must_use]
#[inline]
pub fn from_vec(vec: Vec<E>) -> Self {
Accumulated { inner: vec }
}
#[must_use]
#[inline]
pub fn into_vec(self) -> Vec<E> {
self.inner
}
}
impl<E> FusedError for Accumulated<E> {
#[inline]
fn combine(&mut self, mut other: Self) {
self.inner.append(&mut other.inner);
}
}
impl<E> Default for Accumulated<E> {
#[must_use]
#[inline]
fn default() -> Self {
Accumulated::new()
}
}
impl<E> Deref for Accumulated<E> {
type Target = Vec<E>;
#[inline]
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<E> DerefMut for Accumulated<E> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<E> Debug for Accumulated<E>
where
E: Debug,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.inner, f)
}
}
impl<E> Display for Accumulated<E>
where
E: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let messages = self.iter().map(ToString::to_string).collect::<Vec<_>>();
write!(
f,
"accumulated collection of {} errors: {messages:#?}",
self.inner.len()
)
}
}
impl<E> std::error::Error for Accumulated<E> where E: Debug + Display {}
impl<E> From<Vec<E>> for Accumulated<E> {
#[inline]
fn from(vec: Vec<E>) -> Self {
Accumulated::from_vec(vec)
}
}
impl<E> From<Accumulated<E>> for Vec<E> {
#[inline]
fn from(acc: Accumulated<E>) -> Self {
acc.into_vec()
}
}
impl<E> From<E> for Accumulated<E> {
#[inline]
fn from(err: E) -> Self {
Accumulated::from_vec(vec![err])
}
}
impl<E> FromIterator<E> for Accumulated<E> {
#[inline]
fn from_iter<T: IntoIterator<Item = E>>(iter: T) -> Self {
let vec = Vec::from_iter(iter);
Accumulated::from_vec(vec)
}
}
impl<E> Extend<E> for Accumulated<E> {
#[inline]
fn extend<T: IntoIterator<Item = E>>(&mut self, iter: T) {
self.inner.extend(iter);
}
}
impl<'a, E> IntoIterator for &'a Accumulated<E> {
type Item = &'a E;
type IntoIter = Iter<'a, E>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, E> IntoIterator for &'a mut Accumulated<E> {
type Item = &'a mut E;
type IntoIter = IterMut<'a, E>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<E> IntoIterator for Accumulated<E> {
type Item = E;
type IntoIter = IntoIter<E>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter()
}
}
pub type Iter<'a, E> = std::slice::Iter<'a, E>;
pub type IterMut<'a, E> = std::slice::IterMut<'a, E>;
pub type IntoIter<E> = std::vec::IntoIter<E>;
impl<E> AsRef<[E]> for Accumulated<E> {
#[inline]
fn as_ref(&self) -> &[E] {
self.inner.as_ref()
}
}
impl<E> AsMut<[E]> for Accumulated<E> {
#[inline]
fn as_mut(&mut self) -> &mut [E] {
self.inner.as_mut()
}
}
impl<E> Borrow<[E]> for Accumulated<E> {
#[inline]
fn borrow(&self) -> &[E] {
self.inner.deref().borrow()
}
}
impl<E> BorrowMut<[E]> for Accumulated<E> {
#[inline]
fn borrow_mut(&mut self) -> &mut [E] {
self.inner.deref_mut().borrow_mut()
}
}
impl<E, I> Index<I> for Accumulated<E>
where
I: SliceIndex<[E]>,
{
type Output = I::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output {
self.inner.deref().index(index)
}
}
impl<E, I> IndexMut<I> for Accumulated<E>
where
I: SliceIndex<[E]>,
{
#[inline]
fn index_mut(&mut self, index: I) -> &mut Self::Output {
self.inner.deref_mut().index_mut(index)
}
}
macro_rules! impl_slice_eq {
([$($vars:tt)*] $lhs:ty, $rhs:ty) => {
impl<E, F, $($vars)*> PartialEq<$rhs> for $lhs
where
E: PartialEq<F>
{
#[inline]
fn eq(&self, other: &$rhs) -> bool {
self[..] == other[..]
}
}
}
}
impl_slice_eq!([] Accumulated<E>, Accumulated<F>);
impl_slice_eq!([] Accumulated<E>, Vec<F>);
impl_slice_eq!([] Vec<E>, Accumulated<F>);
impl_slice_eq!([] Accumulated<E>, [F]);
impl_slice_eq!([][E], Accumulated<F>);
impl_slice_eq!([] Accumulated<E>, &[F]);
impl_slice_eq!([] & [E], Accumulated<F>);
impl_slice_eq!([const N: usize] Accumulated<E>, [F; N]);
impl_slice_eq!([const N: usize] [E; N], Accumulated<F>);
impl_slice_eq!([const N: usize] Accumulated<E>, &[F; N]);
impl_slice_eq!([const N: usize] &[E; N], Accumulated<F>);
impl<E> PartialOrd<Vec<E>> for Accumulated<E>
where
E: PartialOrd,
{
#[inline]
fn partial_cmp(&self, other: &Vec<E>) -> Option<std::cmp::Ordering> {
self.inner.partial_cmp(other)
}
}
impl<E> PartialOrd<Accumulated<E>> for Vec<E>
where
E: PartialOrd,
{
#[inline]
fn partial_cmp(&self, other: &Accumulated<E>) -> Option<std::cmp::Ordering> {
self.partial_cmp(&other.inner)
}
}