Skip to content

Commit 9d20d5e

Browse files
committed
Unify error handling to have IpcError and TryRecvError be the main error
types. These types will give the Bincode error, Io errors (which are converted from platform errors) and Disconnect. Additionally we now use the thiserror crate which removes some of the code. Signed-off-by: Narfinger <[email protected]>
1 parent d918d57 commit 9d20d5e

File tree

11 files changed

+130
-199
lines changed

11 files changed

+130
-199
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ futures-channel = { version = "0.3.31", optional = true }
3838
futures-core = { version = "0.3.31", optional = true }
3939
libc = "0.2.162"
4040
serde = { version = "1.0", features = ["rc"] }
41+
thiserror = "2.0.12"
4142
uuid = { version = "1", features = ["v4"] }
4243

4344
[target.'cfg(any(target_os = "linux", target_os = "openbsd", target_os = "freebsd", target_os = "illumos"))'.dependencies]

src/asynch.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
// option. This file may not be copied, modified, or distributed
88
// except according to those terms.
99

10+
use crate::error::SerializationError;
1011
use crate::ipc::{
1112
self, IpcMessage, IpcReceiver, IpcReceiverSet, IpcSelectionResult, IpcSender, OpaqueIpcReceiver,
1213
};
@@ -96,7 +97,7 @@ impl<T> Stream for IpcStream<T>
9697
where
9798
T: for<'de> Deserialize<'de> + Serialize,
9899
{
99-
type Item = Result<T, bincode::Error>;
100+
type Item = Result<T, SerializationError>;
100101

101102
fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Option<Self::Item>> {
102103
let recv = Pin::new(&mut self.0);

src/error.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use std::fmt::Display;
2+
use std::io;
3+
4+
use thiserror::Error;
5+
6+
#[derive(Debug, Error)]
7+
/// An error that occurs for serialization or deserialization
8+
pub struct SerializationError(#[from] pub(crate) bincode::Error);
9+
10+
impl Display for SerializationError {
11+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12+
write!(f, "Serialization error")
13+
}
14+
}
15+
16+
#[derive(Debug, Error)]
17+
pub enum IpcError {
18+
#[error("Error in decoding or encoding: {0}")]
19+
SerializationError(#[from] SerializationError),
20+
#[error("Error in IO: {0}")]
21+
Io(#[from] io::Error),
22+
#[error("Ipc Disconnected")]
23+
Disconnected,
24+
}
25+
26+
#[derive(Debug, Error)]
27+
pub enum TryRecvError {
28+
#[error("IPC error")]
29+
IpcError(#[from] IpcError),
30+
#[error("Channel empty")]
31+
Empty,
32+
}

src/ipc.rs

Lines changed: 13 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,17 @@
77
// option. This file may not be copied, modified, or distributed
88
// except according to those terms.
99

10+
use crate::error::SerializationError;
1011
use crate::platform::{self, OsIpcChannel, OsIpcReceiver, OsIpcReceiverSet, OsIpcSender};
1112
use crate::platform::{
1213
OsIpcOneShotServer, OsIpcSelectionResult, OsIpcSharedMemory, OsOpaqueIpcChannel,
1314
};
15+
use crate::{IpcError, TryRecvError};
1416

1517
use bincode;
1618
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
1719
use std::cell::RefCell;
1820
use std::cmp::min;
19-
use std::error::Error as StdError;
2021
use std::fmt::{self, Debug, Formatter};
2122
use std::io;
2223
use std::marker::PhantomData;
@@ -37,57 +38,6 @@ thread_local! {
3738
const { RefCell::new(Vec::new()) }
3839
}
3940

40-
#[derive(Debug)]
41-
pub enum IpcError {
42-
Bincode(bincode::Error),
43-
Io(io::Error),
44-
Disconnected,
45-
}
46-
47-
impl fmt::Display for IpcError {
48-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
49-
match *self {
50-
IpcError::Bincode(ref err) => write!(fmt, "bincode error: {err}"),
51-
IpcError::Io(ref err) => write!(fmt, "io error: {err}"),
52-
IpcError::Disconnected => write!(fmt, "disconnected"),
53-
}
54-
}
55-
}
56-
57-
impl StdError for IpcError {
58-
fn source(&self) -> Option<&(dyn StdError + 'static)> {
59-
match *self {
60-
IpcError::Bincode(ref err) => Some(err),
61-
IpcError::Io(ref err) => Some(err),
62-
IpcError::Disconnected => None,
63-
}
64-
}
65-
}
66-
67-
#[derive(Debug)]
68-
pub enum TryRecvError {
69-
IpcError(IpcError),
70-
Empty,
71-
}
72-
73-
impl fmt::Display for TryRecvError {
74-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
75-
match *self {
76-
TryRecvError::IpcError(ref err) => write!(fmt, "ipc error: {err}"),
77-
TryRecvError::Empty => write!(fmt, "empty"),
78-
}
79-
}
80-
}
81-
82-
impl StdError for TryRecvError {
83-
fn source(&self) -> Option<&(dyn StdError + 'static)> {
84-
match *self {
85-
TryRecvError::IpcError(ref err) => Some(err),
86-
TryRecvError::Empty => None,
87-
}
88-
}
89-
}
90-
9141
/// Create a connected [IpcSender] and [IpcReceiver] that
9242
/// transfer messages of a given type provided by type `T`
9343
/// or inferred by the types of messages sent by the sender.
@@ -248,15 +198,18 @@ where
248198
{
249199
/// Blocking receive.
250200
pub fn recv(&self) -> Result<T, IpcError> {
251-
self.os_receiver.recv()?.to().map_err(IpcError::Bincode)
201+
self.os_receiver
202+
.recv()?
203+
.to()
204+
.map_err(IpcError::SerializationError)
252205
}
253206

254207
/// Non-blocking receive
255208
pub fn try_recv(&self) -> Result<T, TryRecvError> {
256209
self.os_receiver
257210
.try_recv()?
258211
.to()
259-
.map_err(IpcError::Bincode)
212+
.map_err(IpcError::SerializationError)
260213
.map_err(TryRecvError::IpcError)
261214
}
262215

@@ -270,7 +223,7 @@ where
270223
self.os_receiver
271224
.try_recv_timeout(duration)?
272225
.to()
273-
.map_err(IpcError::Bincode)
226+
.map_err(IpcError::SerializationError)
274227
.map_err(TryRecvError::IpcError)
275228
}
276229

@@ -364,7 +317,7 @@ where
364317
}
365318

366319
/// Send data across the channel to the receiver.
367-
pub fn send(&self, data: T) -> Result<(), bincode::Error> {
320+
pub fn send(&self, data: T) -> Result<(), IpcError> {
368321
let mut bytes = Vec::with_capacity(4096);
369322
OS_IPC_CHANNELS_FOR_SERIALIZATION.with(|os_ipc_channels_for_serialization| {
370323
OS_IPC_SHARED_MEMORY_REGIONS_FOR_SERIALIZATION.with(
@@ -377,7 +330,7 @@ where
377330
let os_ipc_shared_memory_regions;
378331
let os_ipc_channels;
379332
{
380-
bincode::serialize_into(&mut bytes, &data)?;
333+
bincode::serialize_into(&mut bytes, &data).map_err(SerializationError)?;
381334
os_ipc_channels = mem::replace(
382335
&mut *os_ipc_channels_for_serialization.borrow_mut(),
383336
old_os_ipc_channels,
@@ -726,7 +679,7 @@ impl IpcMessage {
726679
}
727680

728681
/// Deserialize the raw data in the contained message into the inferred type.
729-
pub fn to<T>(mut self) -> Result<T, bincode::Error>
682+
pub fn to<T>(mut self) -> Result<T, SerializationError>
730683
where
731684
T: for<'de> Deserialize<'de> + Serialize,
732685
{
@@ -744,7 +697,7 @@ impl IpcMessage {
744697
.map(Some)
745698
.collect(),
746699
);
747-
let result = bincode::deserialize(&self.data[..]);
700+
let result = bincode::deserialize(&self.data[..]).map_err(|e| e.into());
748701
*os_ipc_shared_memory_regions_for_deserialization.borrow_mut() =
749702
old_ipc_shared_memory_regions_for_deserialization;
750703
mem::swap(
@@ -886,7 +839,7 @@ where
886839
))
887840
}
888841

889-
pub fn accept(self) -> Result<(IpcReceiver<T>, T), bincode::Error> {
842+
pub fn accept(self) -> Result<(IpcReceiver<T>, T), IpcError> {
890843
let (os_receiver, ipc_message) = self.os_server.accept()?;
891844
Ok((
892845
IpcReceiver {

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ pub mod asynch;
3232
#[cfg(all(not(feature = "force-inprocess"), target_os = "windows"))]
3333
extern crate windows;
3434

35+
mod error;
3536
pub mod ipc;
3637
pub mod platform;
3738
pub mod router;
3839

3940
#[cfg(test)]
4041
mod test;
4142

42-
pub use bincode::{Error, ErrorKind};
43+
pub use error::{IpcError, TryRecvError};

src/platform/inprocess/mod.rs

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,19 @@
77
// option. This file may not be copied, modified, or distributed
88
// except according to those terms.
99

10-
use crate::ipc::{self, IpcMessage};
11-
use bincode;
10+
use crate::ipc::IpcMessage;
1211
use crossbeam_channel::{self, Receiver, RecvTimeoutError, Select, Sender, TryRecvError};
1312
use std::cell::{Ref, RefCell};
1413
use std::cmp::PartialEq;
1514
use std::collections::hash_map::HashMap;
16-
use std::error::Error as StdError;
1715
use std::fmt::{self, Debug, Formatter};
1816
use std::io;
1917
use std::ops::{Deref, RangeFrom};
2018
use std::slice;
2119
use std::sync::{Arc, LazyLock, Mutex};
2220
use std::time::Duration;
2321
use std::usize;
22+
use thiserror::Error;
2423
use uuid::Uuid;
2524

2625
#[derive(Clone)]
@@ -387,11 +386,15 @@ impl OsIpcSharedMemory {
387386
}
388387
}
389388

390-
#[derive(Debug, PartialEq)]
389+
#[derive(Debug, PartialEq, Error)]
391390
pub enum ChannelError {
391+
#[error("Channel Closed")]
392392
ChannelClosedError,
393+
#[error("Broken Pipe")]
393394
BrokenPipeError,
395+
#[error("Channel Empty")]
394396
ChannelEmpty,
397+
#[error("Unknown Error")]
395398
UnknownError,
396399
}
397400

@@ -402,42 +405,23 @@ impl ChannelError {
402405
}
403406
}
404407

405-
impl fmt::Display for ChannelError {
406-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
407-
match *self {
408-
ChannelError::ChannelClosedError => write!(fmt, "channel closed"),
409-
ChannelError::BrokenPipeError => write!(fmt, "broken pipe"),
410-
ChannelError::ChannelEmpty => write!(fmt, "channel empty"),
411-
ChannelError::UnknownError => write!(fmt, "unknown error"),
412-
}
413-
}
414-
}
415-
416-
impl StdError for ChannelError {}
417-
418-
impl From<ChannelError> for bincode::Error {
419-
fn from(crossbeam_error: ChannelError) -> Self {
420-
io::Error::from(crossbeam_error).into()
421-
}
422-
}
423-
424-
impl From<ChannelError> for ipc::IpcError {
408+
impl From<ChannelError> for crate::IpcError {
425409
fn from(error: ChannelError) -> Self {
426410
match error {
427-
ChannelError::ChannelClosedError => ipc::IpcError::Disconnected,
428-
e => ipc::IpcError::Bincode(io::Error::from(e).into()),
411+
ChannelError::ChannelClosedError => crate::IpcError::Disconnected,
412+
e => crate::IpcError::Io(io::Error::from(e).into()),
429413
}
430414
}
431415
}
432416

433-
impl From<ChannelError> for ipc::TryRecvError {
417+
impl From<ChannelError> for crate::TryRecvError {
434418
fn from(error: ChannelError) -> Self {
435419
match error {
436420
ChannelError::ChannelClosedError => {
437-
ipc::TryRecvError::IpcError(ipc::IpcError::Disconnected)
421+
crate::TryRecvError::IpcError(crate::IpcError::Disconnected)
438422
},
439-
ChannelError::ChannelEmpty => ipc::TryRecvError::Empty,
440-
e => ipc::TryRecvError::IpcError(ipc::IpcError::Bincode(io::Error::from(e).into())),
423+
ChannelError::ChannelEmpty => crate::TryRecvError::Empty,
424+
e => crate::TryRecvError::IpcError(crate::IpcError::Io(io::Error::from(e).into())),
441425
}
442426
}
443427
}

0 commit comments

Comments
 (0)