-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
We use `UnixStream::pair()` a few times and reimplement binary ser/de each time. Add an abstraction that does the serde (`BinSerDe`) and buffer ceremony (`BinPipe`) for us. Fixes #471.
- Loading branch information
Showing
5 changed files
with
202 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
//! Binary serialization, and an implementation over Unix pipes. | ||
use std::{ | ||
io::{self, Read, Write}, | ||
marker::PhantomData, | ||
os::unix::net::UnixStream, | ||
}; | ||
|
||
/// Serialization/deserialization trait using a byte array as storage. | ||
pub trait BinSerDe<const N: usize> { | ||
fn serialize(&self) -> [u8; N]; | ||
fn deserialize(val: [u8; N]) -> Self; | ||
} | ||
|
||
/// A pipe abstracting over a [UnixStream] with easier | ||
/// binary serialization, to help with the buffer sizes and ser/de steps. | ||
/// Uses [UnixStream::pair()]. | ||
pub fn pair<const N1: usize, T1: BinSerDe<N1>, const N2: usize, T2: BinSerDe<N2>>( | ||
) -> io::Result<(BinPipe<N1, T1, N2, T2>, BinPipe<N2, T2, N1, T1>)> { | ||
let (a, b) = UnixStream::pair()?; | ||
Ok(( | ||
BinPipe { | ||
sock: a, | ||
_t1: PhantomData::<T1>, | ||
_t2: PhantomData::<T2>, | ||
}, | ||
BinPipe { | ||
sock: b, | ||
_t1: PhantomData::<T2>, | ||
_t2: PhantomData::<T1>, | ||
}, | ||
)) | ||
} | ||
|
||
/// A binary pipe that can send and recieve typed messages. | ||
/// | ||
/// By default, the types of the [BinPipe::write()] and [BinPipe::read()] | ||
/// messages are the same, but you can specify extra generic arguments to make | ||
/// them differ. In this case, T1 is the type in [BinPipe::write()] | ||
/// and T2 is returned from [BinPipe::read()]. | ||
pub struct BinPipe<const N1: usize, T1: BinSerDe<N1>, const N2: usize = N1, T2: BinSerDe<N2> = T1> { | ||
pub sock: UnixStream, | ||
_t1: PhantomData<T1>, | ||
_t2: PhantomData<T2>, | ||
} | ||
|
||
impl<const N1: usize, const N2: usize, T1: BinSerDe<N1>, T2: BinSerDe<N2>> BinPipe<N1, T1, N2, T2> { | ||
/// Write `T` to the pipe. | ||
pub fn write(&mut self, val: &T1) -> io::Result<()> { | ||
self.sock.write_all(&val.serialize())?; | ||
Ok(()) | ||
} | ||
/// Read `T` from the pipe. | ||
pub fn read(&mut self) -> io::Result<T2> { | ||
let mut buf = [0u8; N2]; | ||
self.sock.read_exact(buf.as_mut_slice())?; | ||
Ok(T2::deserialize(buf)) | ||
} | ||
} | ||
|
||
impl BinSerDe<4> for i32 { | ||
fn serialize(&self) -> [u8; 4] { | ||
self.to_ne_bytes() | ||
} | ||
fn deserialize(val: [u8; 4]) -> Self { | ||
i32::from_ne_bytes(val) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
pub fn single_type_send_recv() { | ||
let (mut tx, mut rx) = pair().unwrap(); | ||
tx.write(&42i32).unwrap(); | ||
assert_eq!(rx.read().unwrap(), 42); | ||
rx.write(&23i32).unwrap(); | ||
assert_eq!(tx.read().unwrap(), 23); | ||
} | ||
|
||
#[test] | ||
pub fn different_send_recv_types() { | ||
impl BinSerDe<1> for u8 { | ||
fn serialize(&self) -> [u8; 1] { | ||
self.to_ne_bytes() | ||
} | ||
fn deserialize(val: [u8; 1]) -> Self { | ||
u8::from_ne_bytes(val) | ||
} | ||
} | ||
|
||
let (mut tx, mut rx) = pair().unwrap(); | ||
tx.write(&42i32).unwrap(); | ||
assert_eq!(rx.read().unwrap(), 42); | ||
rx.write(&23u8).unwrap(); | ||
assert_eq!(tx.read().unwrap(), 23); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.