Added Channel bounds.

Fortune for comfork's current commit: Half blessing − 半吉
master
Avril 3 years ago
parent b9128eba4b
commit 2a2e3c00aa
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -12,3 +12,4 @@ cfg-if = "1.0.0"
libc = "0.2.99" libc = "0.2.99"
once_cell = "1.8.0" once_cell = "1.8.0"
serde = { version = "1.0.129", features = ["derive"] } serde = { version = "1.0.129", features = ["derive"] }
serde_cbor = "0.11.2"

@ -1,16 +1,41 @@
//! `Channel<T>`: Move objects between parent and child processes. //! `Channel<T>`: Move objects between parent and child processes.
use super::*; use super::*;
use bytes::Buf; use bytes::{
Buf,
BufMut,
Bytes,
};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::{fmt, error}; use std::{fmt, error};
use std::io::{ use std::io::{
self, self,
Read, Read,
Write, Write,
Cursor,
};
use serde::{
Serialize,
de::DeserializeOwned,
}; };
use sys::pipe; 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. //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. /// Controls how objects are sent through the streams.
@ -24,6 +49,10 @@ pub trait TransferMethod
/// This can be set to `()`. /// This can be set to `()`.
type State; 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. /// Serialise the object `T` to a byte buffer for sending.
fn send<T>(state: &mut Self::State, obj: &T) -> Result<Self::Buffer, Error>; 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. /// 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 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.) /// Send objects through the stream as bitwise copied (unsafe.)
@ -47,7 +85,29 @@ pub struct TransferBitwise;
impl TransferMethod for 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. /// Send objects of type `T` through parent-child streams.
@ -75,18 +135,19 @@ pub struct Receiver<T, M: ?Sized + TransferMethod = TransferSerial>
_mathod: PhantomData<M>, _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() Sender::<_, TransferSerial>::new()
} }
// TODO: TransferBitwise is very unsafe, document that here. // 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() 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. // TODO: TransferBitwise is very unsafe, document that here.
pub unsafe fn new() -> (Self, Receiver<T, TransferBitwise>) 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>) pub fn new() -> (Self, Receiver<T, TransferSerial>)
{ {
todo!() todo!()
} }
} }
//TODO: Re-do. Do not use generics on the Error type...
// It does NOT need to hold the type information or value. /// The kind of channel error
pub struct Error; //TODO: ... #[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! { remove! {
/// The kind of channel error /// The kind of channel error
#[derive(Debug)] #[derive(Debug)]

Loading…
Cancel
Save