@ -1,16 +1,41 @@
//! `Channel<T>`: Move objects between parent and child processes.
use super ::* ;
use bytes ::Buf ;
use bytes ::{
Buf ,
BufMut ,
Bytes ,
} ;
use std ::marker ::PhantomData ;
use std ::{ fmt , error } ;
use std ::io ::{
self ,
Read ,
Write ,
Cursor ,
} ;
use serde ::{
Serialize ,
de ::DeserializeOwned ,
} ;
use sys ::pipe ;
/// A value that can be sent through a serial `Channel`
///
/// Bitwise channels can take `ChannelBitwiseValue` objects.
pub trait ChannelSerialValue : Serialize + DeserializeOwned { }
impl < T : ? Sized > ChannelSerialValue for T
where T : Serialize + DeserializeOwned { }
/// A value that can be sent through a bitwise `Channel`
///
/// Serial channels require `ChannelSerialValue`.
pub trait ChannelBitwiseValue : Send + Unpin { }
impl < T : ? Sized > ChannelBitwiseValue for T
where T : Send + Unpin { }
//TODO: We can create a non-stream version of this using a memory mapped ring-buffer on an fd shared between parent and child. (i.e: map two pages, the first and second one pointing to the start of the file). But that might be unneeded or too much work for this project's scope.
/// Controls how objects are sent through the streams.
@ -24,6 +49,10 @@ pub trait TransferMethod
/// This can be set to `()`.
type State ;
/// Error for the send/recv conversion.
/// Must be able to convert into `channel::Error`.
type Error : Into < Error > ;
/// Serialise the object `T` to a byte buffer for sending.
fn send < T > ( state : & mut Self ::State , obj : & T ) -> Result < Self ::Buffer , Error > ;
/// Read the object `T` from a byte buffer that was read from the pipe.
@ -38,7 +67,16 @@ pub struct TransferSerial;
impl TransferMethod for TransferSerial
{
type Buffer = Cursor < Vec < u8 > > ;
type State = ( ) ;
type Error = Error ;
fn send < T > ( _ : & mut Self ::State , obj : & T ) -> Result < Self ::Buffer , Error > {
todo! ( )
}
fn recv < T , B : Buf > ( _ : & mut Self ::State , buffer : B ) -> Result < T , Error > {
todo! ( )
}
}
/// Send objects through the stream as bitwise copied (unsafe.)
@ -47,7 +85,29 @@ pub struct TransferBitwise;
impl TransferMethod for TransferBitwise
{
type Buffer = Bytes ;
type State = ( ) ;
type Error = std ::convert ::Infallible ;
fn send < T > ( _ : & mut Self ::State , obj : & T ) -> Result < Self ::Buffer , Error > {
let bytes = unsafe {
std ::slice ::from_raw_parts ( obj as * const T as * const _ , std ::mem ::size_of ::< T > ( ) )
} ;
Ok ( bytes . into ( ) )
}
fn recv < T , B : Buf > ( _ : & mut Self ::State , mut buffer : B ) -> Result < T , Error > {
use std ::mem ::{
self ,
MaybeUninit ,
} ;
let mut value : MaybeUninit < T > = MaybeUninit ::uninit ( ) ;
unsafe {
let slice = std ::slice ::from_raw_parts_mut ( & mut value as * mut MaybeUninit < T > as * mut _ , mem ::size_of ::< T > ( ) ) ;
buffer . copy_to_slice ( slice ) ;
Ok ( value . assume_init ( ) )
}
}
}
/// Send objects of type `T` through parent-child streams.
@ -75,18 +135,19 @@ pub struct Receiver<T, M: ?Sized + TransferMethod = TransferSerial>
_mathod : PhantomData < M > ,
}
#[ inline ] pub fn pair < T > ( ) -> ( Sender < T , TransferSerial > , Receiver < T , TransferSerial > )
#[ inline ] pub fn pair < T : ChannelSerialValue > ( ) -> ( Sender < T , TransferSerial > , Receiver < T , TransferSerial > )
{
Sender ::< _ , TransferSerial > ::new ( )
}
// TODO: TransferBitwise is very unsafe, document that here.
#[ inline ] pub unsafe fn pair_bitwise < T > ( ) -> ( Sender < T , TransferBitwise > , Receiver < T , TransferBitwise > )
#[ inline ] pub unsafe fn pair_bitwise < T : ChannelBitwiseValue > ( ) -> ( Sender < T , TransferBitwise > , Receiver < T , TransferBitwise > )
{
Sender ::< _ , TransferBitwise > ::new ( )
}
impl < T > Sender < T , TransferBitwise >
// TODO: What bounds should we have on this, if any? Send? Unpin? Maybe even restricted to Copy.
impl < T : ChannelBitwiseValue > Sender < T , TransferBitwise >
{
// TODO: TransferBitwise is very unsafe, document that here.
pub unsafe fn new ( ) -> ( Self , Receiver < T , TransferBitwise > )
@ -95,16 +156,56 @@ impl<T> Sender<T, TransferBitwise>
}
}
impl < T > Sender < T , TransferSerial >
impl < T : ChannelSerialValue > Sender < T , TransferSerial >
{
pub fn new ( ) -> ( Self , Receiver < T , TransferSerial > )
{
todo! ( )
}
}
//TODO: Re-do. Do not use generics on the Error type...
// It does NOT need to hold the type information or value.
pub struct Error ; //TODO: ...
/// The kind of channel error
#[ derive(Debug) ]
#[ non_exhaustive ]
pub enum ErrorKind
{
Unknown ,
Serialisation ( serde_cbor ::Error ) ,
Deserialisation ( serde_cbor ::Error ) ,
IO ( io ::Error ) ,
}
/// An error in a channel operation.
#[ derive(Debug) ]
pub struct Error ( Box < ( ErrorKind , Option < bool > ) > ) ;
impl From < ( ErrorKind , bool ) > for Error
{
#[ inline ] fn from ( ( k , s ) : ( ErrorKind , bool ) ) -> Self
{
let from = ( k , Some ( s ) ) ;
Self ( Box ::new ( from ) )
}
}
impl From < ErrorKind > for Error
{
fn from ( from : ErrorKind ) -> Self
{
Self ( Box ::new ( ( from , None ) ) )
}
}
impl From < std ::convert ::Infallible > for Error
{
#[ inline ] fn from ( from : std ::convert ::Infallible ) -> Self
{
match from { }
}
}
remove ! {
/// The kind of channel error
#[ derive(Debug) ]