1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use anyhow::Result;

/// Data that can be sent to and received by a transport.
///
/// This is a marker trait that ensures that data sent between transports is:
/// * [`Send`]
/// * [`Sync`]
/// * has lifetime `'static`
///
/// The user defines which types of messages their transport uses, and this trait acts as a
/// minimum bound for all message types. However, for different transport implementations, there
/// may be additional bounds placed on message types, such as for transports using a network, in
/// which data is sent as a byte sequence:
/// * [`TryIntoBytes`] if the message should be able to be converted into a byte sequence
/// * [`TryFromBytes`] if the message should be able to be constructed from a byte sequence
///
/// This trait is automatically implemented for all types matching these criteria.
pub trait Message: Send + Sync + 'static {}

impl<T> Message for T where T: Send + Sync + 'static {}

/// Data that can potentially be converted into a sequence of bytes.
///
/// The transport implementation may wish to handle messages as a byte sequence, for example
/// if it communicates over a network.
/// This trait can be used as a bound to ensure that messages can be converted into a byte form.
///
/// See [`TryFromBytes`] for the receiving counterpart.
#[cfg_attr(
    feature = "bincode",
    doc = r##"

# [`bincode`] + [`serde`] support

With the `bincode` feature enabled, this trait will automatically be implemented for types which
implement [`serde::Serialize`].
"##
)]
pub trait TryIntoBytes {
    /// Performs the conversion.
    fn try_into_bytes(self) -> Result<Vec<u8>>;
}

/// Data that can potentially be converted from a sequence of bytes into this type.
///
/// The transport implementation may wish to handle messages as a byte sequence, for example
/// if it communicates over a network.
/// This trait can be used as a bound to ensure that messages can be converted from a byte form.
///
/// See [`TryIntoBytes`] for the sending counterpart.
#[cfg_attr(
    feature = "bincode",
    doc = r##"

# [`bincode`] + [`serde`] support

With the `bincode` feature enabled, this trait will automatically be implemented for types which
implement [`serde::de::DeserializeOwned`].
"##
)]
pub trait TryFromBytes: Sized {
    /// Performs the conversion.
    fn try_from_bytes(buf: &[u8]) -> Result<Self>;
}

#[cfg(feature = "bincode")]
impl<T> TryIntoBytes for T
where
    T: serde::Serialize,
{
    fn try_into_bytes(self) -> Result<Vec<u8>> {
        bincode::serialize(&self).map_err(anyhow::Error::new)
    }
}

#[cfg(feature = "bincode")]
impl<T> TryFromBytes for T
where
    T: serde::de::DeserializeOwned,
{
    fn try_from_bytes(buf: &[u8]) -> Result<Self> {
        bincode::deserialize(buf).map_err(anyhow::Error::new)
    }
}