1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
use super::WrappedError; use crate::{ channel::{Channel, ForkHandle}, kind, kind::{ConstructResult, DeconstructResult, Future}, Kind, }; use anyhow::Error; use core::fmt::{self, Debug, Display, Formatter}; use futures::{SinkExt, StreamExt}; use std::error::Error as StdError; use void::Void; #[derive(Kind)] struct ErrorShim { source: Option<Box<ErrorShim>>, debug: String, display: String, } impl Display for ErrorShim { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}", self.display) } } impl Debug for ErrorShim { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}", self.debug) } } impl StdError for ErrorShim { fn source(&self) -> Option<&(dyn StdError + 'static)> { self.source .as_ref() .map(|item| item.as_ref() as &dyn StdError) } } impl<T: StdError + ?Sized> From<&T> for ErrorShim { fn from(input: &T) -> Self { ErrorShim { source: input.source().map(|e| Box::new(ErrorShim::from(e))), debug: format!("{:?}", input), display: format!("{}", input), } } } #[kind] impl Kind for Error { type ConstructItem = ForkHandle; type ConstructError = WrappedError<Void>; type ConstructFuture = Future<ConstructResult<Self>>; type DeconstructItem = (); type DeconstructError = WrappedError<Void>; type DeconstructFuture = Future<DeconstructResult<Self>>; fn deconstruct<C: Channel<Self::DeconstructItem, Self::ConstructItem>>( self, mut channel: C, ) -> Self::DeconstructFuture { Box::pin(async move { Ok(channel .send(channel.fork(ErrorShim::from(&*self)).await?) .await .map_err(WrappedError::Send)?) }) } fn construct<C: Channel<Self::ConstructItem, Self::DeconstructItem>>( mut channel: C, ) -> Self::ConstructFuture { Box::pin(async move { let handle = channel.next().await.ok_or(WrappedError::Insufficient { got: 0, expected: 1, })?; Ok(channel.get_fork::<ErrorShim>(handle).await?.into()) }) } }