//! Responders are objects that produce [MockFn] responses. //! //! They may use the [crate::respond] infrastructure. use crate::{ alloc::Box, call_pattern::{downcast_box, PatternResult}, output::{GetOutput, Kind}, private::AnswerClosure, AnyBox, MockFn, }; /// Type-erased responder which can be stored directly in the Unimock instance. pub(crate) enum DynResponder { Return(DynReturnResponder), Answer(DynAnswerResponder), ApplyDefaultImpl, Unmock, Panic(Box), } /// A responder that returns some value converted into the function's output. pub struct Returner(pub(crate) Box + Send + Sync + 'static>); impl Returner { pub(crate) fn get_output( &self, ) -> Option<<::Return as GetOutput>::Output<'_>> { self.0.get_mock_output() } } pub(crate) struct Answerer { pub answer_closure: AnswerClosure, } /// A trait for turning things into a [Returner] for [MockFn]. #[doc(hidden)] pub trait IntoReturner { fn into_returner(self) -> Returner; } impl + Send + Sync + 'static> IntoReturner for R { fn into_returner(self) -> Returner { Returner(Box::new(self)) } } /// A glue trait for adapting [GetOutput], which is independent of [MockFn], /// to fit together with [MockFn]'s signature. pub(crate) trait GetMockOutput { fn get_mock_output(&self) -> Option<<::Return as GetOutput>::Output<'_>>; } impl GetMockOutput for G where for<'u> G: GetOutput = <::Return as GetOutput>::Output<'u>>, { fn get_mock_output( &self, ) -> Option<<<::OutputKind as Kind>::Return as GetOutput>::Output<'_>> { ::output(self) } } pub(crate) struct DynReturnResponder(AnyBox); pub(crate) struct DynAnswerResponder(AnyBox); /// Trait for downcasting type-erased responders to respective [MockFn]s. pub(crate) trait DowncastResponder { type Downcasted; fn downcast(&self) -> PatternResult<&Self::Downcasted>; } impl DowncastResponder for DynReturnResponder { type Downcasted = Returner; fn downcast(&self) -> PatternResult<&Self::Downcasted> { downcast_box(&self.0) } } impl DowncastResponder for DynAnswerResponder { type Downcasted = Answerer; fn downcast(&self) -> PatternResult<&Self::Downcasted> { downcast_box(&self.0) } } impl Returner { pub(crate) fn into_dyn_responder(self) -> DynResponder { DynResponder::Return(DynReturnResponder(Box::new(self))) } } impl Answerer { pub fn into_dyn_responder(self) -> DynResponder { DynResponder::Answer(DynAnswerResponder(Box::new(self))) } }