#![allow(unused_imports, dead_code, clippy::module_inception)]
#![warn(missing_docs)]
use std::fmt;
pub type TabernaId = u64;
pub type MessageType = u32;
pub type PeerMessageId = u32;
pub const A3_MESSAGE_TYPE_BASE: MessageType = 0x0100_0000;
pub const A1_MESSAGE_TYPE_MAX: MessageType = 0x0000_FFFF;
pub const A2_MESSAGE_TYPE_BASE: MessageType = A1_MESSAGE_TYPE_MAX + 1;
pub const A2_MESSAGE_TYPE_MAX: MessageType = A3_MESSAGE_TYPE_BASE - 1;
pub const A3_MESSAGE_TYPE_MAX_OFFSET: MessageType = MessageType::MAX - A3_MESSAGE_TYPE_BASE;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum MessagePriorityClass {
A1,
A2,
A3,
}
pub const fn classify_message_priority(msg_type: MessageType) -> MessagePriorityClass {
if msg_type <= A1_MESSAGE_TYPE_MAX {
MessagePriorityClass::A1
} else if msg_type <= A2_MESSAGE_TYPE_MAX {
MessagePriorityClass::A2
} else {
MessagePriorityClass::A3
}
}
pub const fn a3_message_type(offset: MessageType) -> MessageType {
match try_a3_message_type(offset) {
Some(msg_type) => msg_type,
None => panic!("A3 message type offset exceeds the A3 range"),
}
}
pub const fn try_a3_message_type(offset: MessageType) -> Option<MessageType> {
A3_MESSAGE_TYPE_BASE.checked_add(offset)
}
pub const MSG_HELLO: MessageType = 1;
pub const MSG_HELLO_RESPONSE: MessageType = 2;
pub const MSG_KEEPALIVE: MessageType = 3;
pub const MSG_ACK: MessageType = 4;
pub const MSG_CLOSE: MessageType = 5;
pub const MSG_ERROR: MessageType = 6;
pub const MSG_RESERVED_7: MessageType = 7;
pub const MSG_BLOB_TRANSFER_CHUNK: MessageType = 8;
pub const MSG_BLOB_TRANSFER_COMPLETE: MessageType = 9;
#[cfg(test)]
mod tests;
macro_rules! define_log_ids {
(
$(#[$enum_meta:meta])*
$vis:vis enum $name:ident {
$(
$(#[$var_meta:meta])*
$variant:ident = $value:expr
),* $(,)?
}
) => {
$(#[$enum_meta])*
#[repr(u32)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
$vis enum $name {
$(
$(#[$var_meta])*
$variant = $value,
)*
}
impl $name {
pub const ALL: &'static [$name] = &[ $( $name::$variant, )* ];
pub fn as_u32(self) -> u32 {
self as u32
}
}
};
}
define_log_ids! {
pub enum LogId {
HandshakeTotalLimit = 1001,
HandshakePerPeerLimit = 1002,
CallisPerPeerLimit = 1003,
OutboundQueueOverrun = 1004,
DuplicateOutboundAck = 1005,
DuplicateOutboundError = 1006,
}
}
macro_rules! define_error_ids {
(
$(#[$enum_meta:meta])*
$vis:vis enum $name:ident {
$(
$(#[$var_meta:meta])*
$variant:ident = $value:expr
),* $(,)?
}
) => {
$(#[$enum_meta])*
#[repr(u32)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
$vis enum $name {
$(
$(#[$var_meta])*
$variant = $value,
)*
}
impl $name {
pub const ALL: &'static [$name] = &[ $( $name::$variant, )* ];
pub fn as_u32(self) -> u32 {
self as u32
}
#[deprecated(note = "Use ErrorId::try_from or u32::try_into instead.")]
pub fn from_u32(value: u32) -> Option<Self> {
Self::from_u32_inner(value)
}
fn from_u32_inner(value: u32) -> Option<Self> {
match value {
$( $value => Some(Self::$variant), )*
_ => None,
}
}
}
impl TryFrom<u32> for $name {
type Error = ();
fn try_from(value: u32) -> Result<Self, Self::Error> {
Self::from_u32_inner(value).ok_or(())
}
}
};
}
pub const ERROR_MESSAGE_MAX_LEN: usize = 1024;
define_error_ids! {
pub enum ErrorId {
UnknownTaberna = 1,
LocalQueueFull = 2,
PeerUnavailable = 3,
RemoteTabernaRejected = 4,
ConnectionLost = 5,
PeerRestarted = 6,
ProtocolViolation = 7,
UnsupportedVersion = 8,
EncodeFailure = 9,
DecodeFailure = 10,
TabernaBusy = 11,
SendTimeout = 12,
BlobCallisWithoutPrimary = 13,
BlobAckWindowExceeded = 14,
BlobStreamNotFound = 15,
BlobStreamOutOfOrder = 16,
BlobStreamIdleTimeout = 17,
BlobStreamMissingChunk = 18,
BlobBufferFull = 19,
AddressMismatch = 20,
TabernaAlreadyRegistered = 21,
InvalidConfig = 22,
DomusClosed = 23,
ReceiveTimeout = 24,
SnapshotNotAvailable = 25,
TabernaShutdown = 26,
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AureliaError {
pub kind: ErrorId,
pub message: Option<String>,
}
impl AureliaError {
pub fn new(kind: ErrorId) -> Self {
Self {
kind,
message: None,
}
}
pub fn with_message(kind: ErrorId, message: impl Into<String>) -> Self {
let mut message = message.into();
if message.len() > ERROR_MESSAGE_MAX_LEN {
let mut idx = ERROR_MESSAGE_MAX_LEN;
while idx > 0 && !message.is_char_boundary(idx) {
idx -= 1;
}
message.truncate(idx);
}
Self {
kind,
message: Some(message),
}
}
}
impl fmt::Display for AureliaError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.message {
Some(message) => write!(f, "{:?}: {}", self.kind, message),
None => write!(f, "{:?}", self.kind),
}
}
}
impl std::error::Error for AureliaError {}