cuprate_types/connection_state.rs
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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
//! [`ConnectionState`].
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "epee")]
use cuprate_epee_encoding::{
error,
macros::bytes::{Buf, BufMut},
EpeeValue, Marker,
};
use strum::{
AsRefStr, Display, EnumCount, EnumIs, EnumString, FromRepr, IntoStaticStr, VariantArray,
};
/// An enumeration of P2P connection states.
///
/// Used in `cuprate_p2p` and `cuprate_rpc_types`.
///
/// Original definition:
/// - <https://github.com/monero-project/monero/blob/893916ad091a92e765ce3241b94e706ad012b62a/src/cryptonote_basic/connection_context.h#L49>
///
/// # Serde
/// This type's `serde` implementation depends on `snake_case`.
///
/// ```rust
/// use cuprate_types::ConnectionState as C;
/// use serde_json::to_string;
///
/// assert_eq!(to_string(&C::BeforeHandshake).unwrap(), r#""before_handshake""#);
/// assert_eq!(to_string(&C::Synchronizing).unwrap(), r#""synchronizing""#);
/// assert_eq!(to_string(&C::Standby).unwrap(), r#""standby""#);
/// assert_eq!(to_string(&C::Idle).unwrap(), r#""idle""#);
/// assert_eq!(to_string(&C::Normal).unwrap(), r#""normal""#);
///
/// assert_eq!(C::BeforeHandshake.to_string(), "before_handshake");
/// assert_eq!(C::Synchronizing.to_string(), "synchronizing");
/// assert_eq!(C::Standby.to_string(), "standby");
/// assert_eq!(C::Idle.to_string(), "idle");
/// assert_eq!(C::Normal.to_string(), "normal");
/// ```
#[derive(
Copy,
Clone,
Default,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
AsRefStr,
Display,
EnumCount,
EnumIs,
EnumString,
FromRepr,
IntoStaticStr,
VariantArray,
)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))] // cuprate-rpc-types depends on snake_case
#[strum(serialize_all = "snake_case")]
#[repr(u8)]
pub enum ConnectionState {
BeforeHandshake,
Synchronizing,
Standby,
Idle,
#[default]
Normal,
}
impl ConnectionState {
/// Convert [`Self`] to a [`u8`].
///
/// ```rust
/// use cuprate_types::ConnectionState as C;
///
/// assert_eq!(C::BeforeHandshake.to_u8(), 0);
/// assert_eq!(C::Synchronizing.to_u8(), 1);
/// assert_eq!(C::Standby.to_u8(), 2);
/// assert_eq!(C::Idle.to_u8(), 3);
/// assert_eq!(C::Normal.to_u8(), 4);
/// ```
pub const fn to_u8(self) -> u8 {
self as u8
}
/// Convert a [`u8`] to a [`Self`].
///
/// # Errors
/// This returns [`None`] if `u > 4`.
///
/// ```rust
/// use cuprate_types::ConnectionState as C;
///
/// assert_eq!(C::from_u8(0), Some(C::BeforeHandshake));
/// assert_eq!(C::from_u8(1), Some(C::Synchronizing));
/// assert_eq!(C::from_u8(2), Some(C::Standby));
/// assert_eq!(C::from_u8(3), Some(C::Idle));
/// assert_eq!(C::from_u8(4), Some(C::Normal));
/// assert_eq!(C::from_u8(5), None);
/// ```
pub const fn from_u8(u: u8) -> Option<Self> {
Some(match u {
0 => Self::BeforeHandshake,
1 => Self::Synchronizing,
2 => Self::Standby,
3 => Self::Idle,
4 => Self::Normal,
_ => return None,
})
}
}
impl From<ConnectionState> for u8 {
fn from(value: ConnectionState) -> Self {
value.to_u8()
}
}
impl TryFrom<u8> for ConnectionState {
type Error = u8;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match Self::from_u8(value) {
Some(s) => Ok(s),
None => Err(value),
}
}
}
#[cfg(feature = "epee")]
impl EpeeValue for ConnectionState {
const MARKER: Marker = u8::MARKER;
fn read<B: Buf>(r: &mut B, marker: &Marker) -> error::Result<Self> {
let u = u8::read(r, marker)?;
Self::from_u8(u).ok_or(error::Error::Format("u8 was greater than 4"))
}
fn write<B: BufMut>(self, w: &mut B) -> error::Result<()> {
let u = self.to_u8();
u8::write(u, w)?;
Ok(())
}
}