pub async fn split<T, E, P, Q, R, F, Fut>(
        self,
        with_parts: F,
    ) -> Result<(T, Result<Chan<R, Tx, Rx>, SessionIncomplete<Tx, Rx>>), E>
    where
        S: Session<Action = Split<P, Q, R>>,
        P: Session,
        Q: Session,
        R: Session,
        F: FnOnce(Chan<P, Tx, Unavailable>, Chan<Q, Unavailable, Rx>) -> Fut,
        Fut: Future<Output = Result<T, E>>,
    {
        use IncompleteHalf::*;
        use SessionIncomplete::*;

        let (tx, rx, drop_tx, drop_rx) = self.unwrap_contents();
        let ((result, maybe_rx), maybe_tx) =
            P::over(tx.unwrap(), Unavailable::default(), |tx_only| async move {
                Q::over(Unavailable::default(), rx.unwrap(), |rx_only| async move {
                    with_parts(tx_only, rx_only).await
                })
                .await
            })
            .await;
        // Unpack and repack the resultant tx and rx or SessionIncomplete to eliminate
        // Available/Unavailable and maximize possible returned things (it's fine to drop the
        // Unavailable end of something if for some reason you split twice)
        let maybe_tx_rx: Result<(Tx, Rx), SessionIncomplete<Tx, Rx>> = match (
            maybe_tx
                .map(|(tx, _)| Ok(tx))
                .unwrap_or_else(|incomplete| incomplete.into_halves().0),
            maybe_rx
                .map(|(_, rx)| Ok(rx))
                .unwrap_or_else(|incomplete| incomplete.into_halves().1),
        ) {
            (Ok(tx), Ok(rx)) => Ok((tx, rx)),
            (Ok(tx), Err(Unclosed)) => Err(RxHalf { tx, rx: Unclosed }),
            (Err(Unclosed), Ok(rx)) => Err(TxHalf { tx: Unclosed, rx }),
            (Ok(tx), Err(Unfinished(rx))) => Err(RxHalf {
                tx,
                rx: Unfinished(rx),
            }),
            (Err(Unfinished(tx)), Ok(rx)) => Err(TxHalf {
                tx: Unfinished(tx),
                rx,
            }),
            (Err(Unfinished(tx)), Err(Unclosed)) => Err(BothHalves {
                tx: Unfinished(tx),
                rx: Unclosed,
            }),
            (Err(Unclosed), Err(Unfinished(rx))) => Err(BothHalves {
                tx: Unclosed,
                rx: Unfinished(rx),
            }),
            (Err(Unclosed), Err(Unclosed)) => Err(BothHalves {
                tx: Unclosed,
                rx: Unclosed,
            }),
            (Err(Unfinished(tx)), Err(Unfinished(rx))) => Err(BothHalves {
                tx: Unfinished(tx),
                rx: Unfinished(rx),
            }),
        };
        Ok((
            result?,
            maybe_tx_rx.map(|(tx, rx)| Chan {
                tx: Some(tx),
                rx: Some(rx),
                drop_tx,
                drop_rx,
                session: PhantomData,
            }),
        ))
    }
/// Split a channel into transmit-only and receive-only ends and manipulate them, potentially
/// concurrently, in the given closure.
///
/// This is akin to [`call`](Chan::call), except the closure is given *two* [`Chan`]s: one which
/// can only do [`Transmit`] operations ([`Send`] and [`Choose`]) and one which can only do
/// [`Receive`] operations ([`Recv`] and [`Offer`]). The result of the call to
/// [`split`](Chan::split) is a re-unified [`Chan`] ready to execute the session `R`.
///
/// # Errors
///
/// The closure must *finish* the session for both the send-only and receive-only ends of the
/// channel and drop or [`close`](Chan::close) each end *before* the future completes. If either
/// end is dropped before finishing its session, or is not closed after finishing its session, a
/// [`SessionIncomplete`] error will be returned instead of a finished channel.
///
/// # Examples
///
/// In this example, both ends of a channel concurrently interact with its split send/receive
/// halves. If the underlying channel implementation allows for parallelism, this simultaneous
/// interaction can be faster than sequentially sending data back and forth.
///
/// ```
/// use dialectic::prelude::*;
/// use dialectic_tokio_mpsc as mpsc;
///
/// # #[tokio::main]
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// type SendAndRecv = Session! {
///     split {
///         -> send Vec<usize>,
///         <- recv String,
///     }
/// };
///
/// let (c1, c2) = SendAndRecv::channel(|| mpsc::channel(1));
///
/// // Spawn a thread to simultaneously send a `Vec<usize>` and receive a `String`:
/// let t1 = tokio::spawn(async move {
///     c1.split(|tx, rx| async move {
///         let send_vec = tokio::spawn(async move {
///             tx.send(vec![1, 2, 3, 4, 5]).await?;
///             Ok::<_, mpsc::Error>(())
///         });
///         let recv_string = tokio::spawn(async move {
///             let (string, _) = rx.recv().await?;
///             Ok::<_, mpsc::Error>(string)
///         });
///         send_vec.await.unwrap()?;
///         let string = recv_string.await.unwrap()?;
///         Ok::<_, mpsc::Error>(string)
///     }).await
/// });
///
/// // Simultaneously *receive* a `Vec<usize>` *from*, and *send* a `String` *to*,
/// // the task above:
/// c2.split(|tx, rx| async move {
///     let send_string = tokio::spawn(async move {
///         tx.send("Hello!".to_string()).await?;
///         Ok::<_, mpsc::Error>(())
///     });
///     let recv_vec = tokio::spawn(async move {
///         let (vec, _) = rx.recv().await?;
///         Ok::<_, mpsc::Error>(vec)
///     });
///
///     // Examine the result values:
///     send_string.await??;
///     let vec = recv_vec.await??;
///     let string = t1.await??.0;
///     assert_eq!(vec, &[1, 2, 3, 4, 5]);
///     assert_eq!(string, "Hello!");
///
///     Ok::<_, Box<dyn std::error::Error>>(())
/// }).await?;
/// #
/// # Ok(())
/// # }
/// ```
Split a channel into transmit-only and receive-only ends and manipulate them, potentially
concurrently, in the given closure.


Split a channel into transmit - only and receive - only ends and manipulate them potentially concurrently in the given closure .
pub async fn split<T, E, P, Q, R, F, Fut>(
        self,
        with_parts: F,
    ) -> Result<(T, Result<Chan<R, Tx, Rx>, SessionIncomplete<Tx, Rx>>), E>
    where
        S: Session<Action = Split<P, Q, R>>,
        P: Session,
        Q: Session,
        R: Session,
        F: FnOnce(Chan<P, Tx, Unavailable>, Chan<Q, Unavailable, Rx>) -> Fut,
        Fut: Future<Output = Result<T, E>>,
    {
        use IncompleteHalf::*;
        use SessionIncomplete::*;
        let (tx, rx, drop_tx, drop_rx) = self.unwrap_contents();
        let ((result, maybe_rx), maybe_tx) =
            P::over(tx.unwrap(), Unavailable::default(), |tx_only| async move {
                Q::over(Unavailable::default(), rx.unwrap(), |rx_only| async move {
                    with_parts(tx_only, rx_only).await
                })
                .await
            })
            .await;
        // Unpack and repack the resultant tx and rx or SessionIncomplete to eliminate
        // Available/Unavailable and maximize possible returned things (it's fine to drop the
        // Unavailable end of something if for some reason you split twice)
        let maybe_tx_rx: Result<(Tx, Rx), SessionIncomplete<Tx, Rx>> = match (
            maybe_tx
                .map(|(tx, _)| Ok(tx))
                .unwrap_or_else(|incomplete| incomplete.into_halves().0),
            maybe_rx
                .map(|(_, rx)| Ok(rx))
                .unwrap_or_else(|incomplete| incomplete.into_halves().1),
        ) {
            (Ok(tx), Ok(rx)) => Ok((tx, rx)),
            (Ok(tx), Err(Unclosed)) => Err(RxHalf { tx, rx: Unclosed }),
            (Err(Unclosed), Ok(rx)) => Err(TxHalf { tx: Unclosed, rx }),
            (Ok(tx), Err(Unfinished(rx))) => Err(RxHalf {
                tx,
                rx: Unfinished(rx),
            }),
            (Err(Unfinished(tx)), Ok(rx)) => Err(TxHalf {
                tx: Unfinished(tx),
                rx,
            }),
            (Err(Unfinished(tx)), Err(Unclosed)) => Err(BothHalves {
                tx: Unfinished(tx),
                rx: Unclosed,
            }),
            (Err(Unclosed), Err(Unfinished(rx))) => Err(BothHalves {
                tx: Unclosed,
                rx: Unfinished(rx),
            }),
            (Err(Unclosed), Err(Unclosed)) => Err(BothHalves {
                tx: Unclosed,
                rx: Unclosed,
            }),
            (Err(Unfinished(tx)), Err(Unfinished(rx))) => Err(BothHalves {
                tx: Unfinished(tx),
                rx: Unfinished(rx),
            }),
        };
        Ok((
            result?,
            maybe_tx_rx.map(|(tx, rx)| Chan {
                tx: Some(tx),
                rx: Some(rx),
                drop_tx,
                drop_rx,
                session: PhantomData,
            }),
        ))
    }
pub async fn split < T , E , P , Q , R , F , Fut > ( self , with_parts : F , ) -> Result < ( T , Result < Chan < R , Tx , Rx > , SessionIncomplete < Tx , Rx > > ) , E > where S : Session < Action = Split < P , Q , R > > , P : Session , Q : Session , R : Session , F : FnOnce ( Chan < P , Tx , Unavailable > , Chan < Q , Unavailable , Rx > ) -> Fut , Fut : Future < Output = Result < T , E > > , { use IncompleteHalf :: * ; use SessionIncomplete :: * ; let ( tx , rx , drop_tx , drop_rx ) = self . unwrap_contents ( ) ; let ( ( result , maybe_rx ) , maybe_tx ) = P :: over ( tx . unwrap ( ) , Unavailable :: default ( ) , | tx_only | async move { Q :: over ( Unavailable :: default ( ) , rx . unwrap ( ) , | rx_only | async move { with_parts ( tx_only , rx_only ) . await } ) . await } ) . await ; // Unpack and repack the resultant tx and rx or SessionIncomplete to eliminate // Available/Unavailable and maximize possible returned things (it's fine to drop the // Unavailable end of something if for some reason you split twice) let maybe_tx_rx : Result < ( Tx , Rx ) , SessionIncomplete < Tx , Rx > > = match ( maybe_tx . map ( | ( tx , _ ) | Ok ( tx ) ) . unwrap_or_else ( | incomplete | incomplete . into_halves ( ) . 0 ) , maybe_rx . map ( | ( _ , rx ) | Ok ( rx ) ) . unwrap_or_else ( | incomplete | incomplete . into_halves ( ) . 1 ) , ) { ( Ok ( tx ) , Ok ( rx ) ) => Ok ( ( tx , rx ) ) , ( Ok ( tx ) , Err ( Unclosed ) ) => Err ( RxHalf { tx , rx : Unclosed } ) , ( Err ( Unclosed ) , Ok ( rx ) ) => Err ( TxHalf { tx : Unclosed , rx } ) , ( Ok ( tx ) , Err ( Unfinished ( rx ) ) ) => Err ( RxHalf { tx , rx : Unfinished ( rx ) , } ) , ( Err ( Unfinished ( tx ) ) , Ok ( rx ) ) => Err ( TxHalf { tx : Unfinished ( tx ) , rx , } ) , ( Err ( Unfinished ( tx ) ) , Err ( Unclosed ) ) => Err ( BothHalves { tx : Unfinished ( tx ) , rx : Unclosed , } ) , ( Err ( Unclosed ) , Err ( Unfinished ( rx ) ) ) => Err ( BothHalves { tx : Unclosed , rx : Unfinished ( rx ) , } ) , ( Err ( Unclosed ) , Err ( Unclosed ) ) => Err ( BothHalves { tx : Unclosed , rx : Unclosed , } ) , ( Err ( Unfinished ( tx ) ) , Err ( Unfinished ( rx ) ) ) => Err ( BothHalves { tx : Unfinished ( tx ) , rx : Unfinished ( rx ) , } ) , } ; Ok ( ( result ? , maybe_tx_rx . map ( | ( tx , rx ) | Chan { tx : Some ( tx ) , rx : Some ( rx ) , drop_tx , drop_rx , session : PhantomData , } ) , ) ) }
Split a channel into transmit-only and receive-only ends and manipulate them, potentially
concurrently, in the given closure.
Split a channel into transmit - only and receive - only ends and manipulate them potentially concurrently in the given closure .
self
with_parts
F
errors
The closure must *finish* the session for both the send-only and receive-only ends of the
channel and drop or [`close`](Chan::close) each end *before* the future completes. If either
end is dropped before finishing its session, or is not closed after finishing its session, a
[`SessionIncomplete`] error will be returned instead of a finished channel.
The closure must * finish * the session for both the send - only and receive - only ends of the channel and drop or [ ` close ` ] ( Chan :: close ) each end * before * the future completes . If either end is dropped before finishing its session or is not closed after finishing its session a [ ` SessionIncomplete ` ] error will be returned instead of a finished channel .
examples
In this example, both ends of a channel concurrently interact with its split send/receive
halves. If the underlying channel implementation allows for parallelism, this simultaneous
interaction can be faster than sequentially sending data back and forth.

```
use dialectic::prelude::*;
use dialectic_tokio_mpsc as mpsc.
In this example both ends of a channel concurrently interact with its split send / receive halves . If the underlying channel implementation allows for parallelism this simultaneous interaction can be faster than sequentially sending data back and forth . ` ` ` use dialectic :: prelude :: * ; use dialectic_tokio_mpsc as mpsc .
#[tokio::main]
None
async fn main() -> result<(), box<dyn std::error::error>> {
type SendAndRecv = Session. {
split {
> send Vec,
<- recv String,
}
}.

let (c1, c2) = SendAndRecv::channel(|| mpsc::channel(1)).

Spawn a thread to simultaneously send a `Vec` and receive a `String`:
let t1 = tokio::spawn(async move {
c1.split(|tx, rx| async move {
let send_vec = tokio::spawn(async move {
tx.send(vec![1, 2, 3, 4, 5]).await?;
Ok::<_, mpsc::Error>(())
});
let recv_string = tokio::spawn(async move {
let (string, _) = rx.recv().await?;
Ok::<_, mpsc::Error>(string)
});
send_vec.await.unwrap()?;
let string = recv_string.await.unwrap()?;
Ok::<_, mpsc::Error>(string)
}).await
}).

Simultaneously *receive* a `Vec` *from*, and *send* a `String` *to*,
the task above:
c2.split(|tx, rx| async move {
let send_string = tokio::spawn(async move {
tx.send("Hello!".to_string()).await?;
Ok::<_, mpsc::Error>(())
});
let recv_vec = tokio::spawn(async move {
let (vec, _) = rx.recv().await?;
Ok::<_, mpsc::Error>(vec)
}).

Examine the result values:
send_string.await??;
let vec = recv_vec.await??;
let string = t1.await??.0;
assert_eq!(vec, &[1, 2, 3, 4, 5]);
assert_eq!(string, "Hello!").


type SendAndRecv = Session . { split { > send Vec < - recv String } } . let ( c1 c2 ) = SendAndRecv :: channel ( || mpsc :: channel ( 1 )) . Spawn a thread to simultaneously send a ` Vec ` and receive a ` String ` : let t1 = tokio :: spawn ( async move { c1 . split ( |tx rx| async move { let send_vec = tokio :: spawn ( async move { tx . send ( vec! [ 1 2 3 4 5 ] ) . await? ; Ok :: <_ mpsc :: Error > (( )) } ) ; let recv_string = tokio :: spawn ( async move { let ( string _ ) = rx . recv () . await? ; Ok :: <_ mpsc :: Error > ( string ) } ) ; send_vec . await . unwrap () ? ; let string = recv_string . await . unwrap () ? ; Ok :: <_ mpsc :: Error > ( string ) } ) . await } ) . Simultaneously * receive * a ` Vec ` * from * and * send * a ` String ` * to * the task above : c2 . split ( |tx rx| async move { let send_string = tokio :: spawn ( async move { tx . send ( " Hello! " . to_string () ) . await? ; Ok :: <_ mpsc :: Error > (( )) } ) ; let recv_vec = tokio :: spawn ( async move { let ( vec _ ) = rx . recv () . await? ; Ok :: <_ mpsc :: Error > ( vec ) } ) . Examine the result values : send_string . await?? ; let vec = recv_vec . await?? ; let string = t1 . await?? . 0 ; assert_eq! ( vec & [ 1 2 3 4 5 ] ) ; assert_eq! ( string " Hello! " ) .
ok(())
None
}
None