use std::convert::Infallible;
use std::fmt;
use std::iter;
use std::marker::PhantomData;
use crate::core::{FormattedFailure, MatchOutcome, TransformMatch};
pub struct MapMatcher<'a, In, Out> {
func: Box<dyn FnOnce(In) -> Out + 'a>,
}
impl<'a, In, Out> fmt::Debug for MapMatcher<'a, In, Out> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MapMatcher").finish_non_exhaustive()
}
}
impl<'a, In, Out> MapMatcher<'a, In, Out> {
pub fn new(func: impl FnOnce(In) -> Out + 'a) -> Self {
Self {
func: Box::new(func),
}
}
}
impl<'a, In, Out> TransformMatch for MapMatcher<'a, In, Out> {
type In = In;
type PosOut = Out;
type NegOut = Out;
type PosFail = Infallible;
type NegFail = Infallible;
fn match_pos(
self,
actual: Self::In,
) -> crate::Result<MatchOutcome<Self::PosOut, Self::PosFail>> {
Ok(MatchOutcome::Success((self.func)(actual)))
}
fn match_neg(
self,
actual: Self::In,
) -> crate::Result<MatchOutcome<Self::PosOut, Self::PosFail>> {
self.match_pos(actual)
}
}
pub struct TryMapMatcher<'a, In, Out> {
func: Box<dyn FnOnce(In) -> crate::Result<Out> + 'a>,
}
impl<'a, In, Out> fmt::Debug for TryMapMatcher<'a, In, Out> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TryMapMatcher").finish_non_exhaustive()
}
}
impl<'a, In, Out> TryMapMatcher<'a, In, Out> {
pub fn new(func: impl FnOnce(In) -> crate::Result<Out> + 'a) -> Self {
Self {
func: Box::new(func),
}
}
}
impl<'a, In, Out> TransformMatch for TryMapMatcher<'a, In, Out> {
type In = In;
type PosOut = Out;
type NegOut = Out;
type PosFail = FormattedFailure;
type NegFail = FormattedFailure;
fn match_pos(
self,
actual: Self::In,
) -> crate::Result<MatchOutcome<Self::PosOut, Self::PosFail>> {
Ok(MatchOutcome::Success((self.func)(actual)?))
}
fn match_neg(
self,
actual: Self::In,
) -> crate::Result<MatchOutcome<Self::PosOut, Self::PosFail>> {
self.match_pos(actual)
}
}
pub struct IterMap<'a, In, Out, I> {
inner: I,
func: Box<dyn Fn(In) -> Out + 'a>,
}
impl<'a, In, Out, I> IterMap<'a, In, Out, I> {
pub(crate) fn new(inner: I, func: Box<dyn Fn(In) -> Out + 'a>) -> Self {
Self { inner, func }
}
}
impl<'a, In, Out, I> fmt::Debug for IterMap<'a, In, Out, I>
where
I: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("IterMap")
.field("inner", &self.inner)
.finish_non_exhaustive()
}
}
impl<'a, In, Out, I> Iterator for IterMap<'a, In, Out, I>
where
I: Iterator<Item = In>,
{
type Item = Out;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(&self.func)
}
}
impl<'a, In, Out, I> DoubleEndedIterator for IterMap<'a, In, Out, I>
where
I: DoubleEndedIterator<Item = In>,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back().map(&self.func)
}
}
impl<'a, In, Out, I> ExactSizeIterator for IterMap<'a, In, Out, I> where
I: ExactSizeIterator<Item = In>
{
}
impl<'a, In, Out, I> iter::FusedIterator for IterMap<'a, In, Out, I> where
I: iter::FusedIterator<Item = In>
{
}
pub struct IterMapMatcher<'a, In, Out, IntoIter> {
func: Box<dyn Fn(In) -> Out + 'a>,
marker: PhantomData<IntoIter>,
}
impl<'a, In, Out, IntoIter> fmt::Debug for IterMapMatcher<'a, In, Out, IntoIter> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("IterMapMatcher").finish_non_exhaustive()
}
}
impl<'a, In, Out, IntoIter> IterMapMatcher<'a, In, Out, IntoIter> {
pub fn new(func: impl Fn(In) -> Out + 'a) -> Self {
Self {
func: Box::new(func),
marker: PhantomData,
}
}
}
impl<'a, In, Out, IntoIter> TransformMatch for IterMapMatcher<'a, In, Out, IntoIter>
where
IntoIter: IntoIterator<Item = In> + 'a,
{
type In = IntoIter;
type PosOut = IterMap<'a, In, Out, IntoIter::IntoIter>;
type NegOut = IterMap<'a, In, Out, IntoIter::IntoIter>;
type PosFail = Infallible;
type NegFail = Infallible;
fn match_pos(
self,
actual: Self::In,
) -> crate::Result<MatchOutcome<Self::PosOut, Self::PosFail>> {
Ok(MatchOutcome::Success(IterMap::new(
actual.into_iter(),
self.func,
)))
}
fn match_neg(
self,
actual: Self::In,
) -> crate::Result<MatchOutcome<Self::NegOut, Self::NegFail>> {
self.match_pos(actual)
}
}
pub struct IterTryMapMatcher<'a, In, Out, IntoIter> {
func: Box<dyn Fn(In) -> crate::Result<Out> + 'a>,
marker: PhantomData<IntoIter>,
}
impl<'a, In, Out, IntoIter> fmt::Debug for IterTryMapMatcher<'a, In, Out, IntoIter> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("IterTryMapMatcher").finish_non_exhaustive()
}
}
impl<'a, In, Out, IntoIter> IterTryMapMatcher<'a, In, Out, IntoIter> {
pub fn new(func: impl Fn(In) -> crate::Result<Out> + 'a) -> Self {
Self {
func: Box::new(func),
marker: PhantomData,
}
}
}
impl<'a, In, Out, IntoIter> TransformMatch for IterTryMapMatcher<'a, In, Out, IntoIter>
where
IntoIter: IntoIterator<Item = In> + 'a,
{
type In = IntoIter;
type PosOut = Vec<Out>;
type NegOut = Vec<Out>;
type PosFail = Infallible;
type NegFail = Infallible;
fn match_pos(
self,
actual: Self::In,
) -> crate::Result<MatchOutcome<Self::PosOut, Self::PosFail>> {
Ok(MatchOutcome::Success(
actual
.into_iter()
.map(self.func)
.collect::<Result<Vec<_>, _>>()?,
))
}
fn match_neg(
self,
actual: Self::In,
) -> crate::Result<MatchOutcome<Self::NegOut, Self::NegFail>> {
self.match_pos(actual)
}
}