0.3.4-alpha.2

This commit is contained in:
2026-09-21 17:21:25 +02:00
parent 27978c3782
commit 4e2be3cc9a
11 changed files with 533 additions and 8 deletions

View File

@@ -0,0 +1,42 @@
// file: crates/common/game-realtime-transport-lib/src/connection.rs
// version: 1
/// Established realtime connection that owns independent send and receive halves.
pub trait RealtimeConnection {
/// Send half produced when this connection is split.
type Sender: crate::RealtimeSender;
/// Receive half produced when this connection is split.
type Receiver: crate::RealtimeReceiver;
/// Consumes the connection and returns independent send and receive halves.
fn split(self) -> (Self::Sender, Self::Receiver);
}
/// Send half of an established realtime connection.
pub trait RealtimeSender {
/// Future returned by [`RealtimeSender::send`].
type SendFuture<'a>: core::future::Future<Output = Result<(), crate::TransportError>>
where
Self: 'a;
/// Future returned by [`RealtimeSender::close`].
type CloseFuture<'a>: core::future::Future<Output = Result<(), crate::TransportError>>
where
Self: 'a;
/// Sends one owned opaque binary message, respecting backend backpressure.
fn send(&mut self, message: crate::TransportMessage) -> Self::SendFuture<'_>;
/// Initiates a clean local transport-level close.
fn close(&mut self) -> Self::CloseFuture<'_>;
}
/// Receive half of an established realtime connection.
pub trait RealtimeReceiver {
/// Future returned by [`RealtimeReceiver::receive`].
type ReceiveFuture<'a>: core::future::Future<Output = Result<crate::TransportReceive, crate::TransportError>>
where
Self: 'a;
/// Receives one binary message or observes a clean remote close.
fn receive(&mut self) -> Self::ReceiveFuture<'_>;
}

View File

@@ -0,0 +1,82 @@
// file: crates/common/game-realtime-transport-lib/src/error.rs
// version: 1
/// Stable transport-neutral category for a realtime operation failure.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TransportErrorKind {
/// An endpoint or transport configuration is invalid.
InvalidConfiguration,
/// A client connection could not be established.
Connect,
/// A server endpoint could not be bound.
Bind,
/// A server could not accept an incoming connection.
Accept,
/// An operation exceeded its configured deadline.
Timeout,
/// A payload exceeds the configured transport bound.
MessageTooLarge,
/// The transport cannot currently accept more outbound data within its configured bounds.
Backpressure,
/// The requested operation requires a connection that is already closed.
Closed,
/// An underlying I/O operation failed.
Io,
/// The backend reported a protocol-level or transport-specific failure.
Protocol,
/// The operation was explicitly aborted or cancelled when that distinction is observable.
Aborted,
}
impl core::fmt::Display for TransportErrorKind {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
return match self {
crate::TransportErrorKind::InvalidConfiguration => formatter.write_str("invalid configuration"),
crate::TransportErrorKind::Connect => formatter.write_str("connect failure"),
crate::TransportErrorKind::Bind => formatter.write_str("bind failure"),
crate::TransportErrorKind::Accept => formatter.write_str("accept failure"),
crate::TransportErrorKind::Timeout => formatter.write_str("operation timed out"),
crate::TransportErrorKind::MessageTooLarge => formatter.write_str("message too large"),
crate::TransportErrorKind::Backpressure => formatter.write_str("transport backpressure"),
crate::TransportErrorKind::Closed => formatter.write_str("connection closed"),
crate::TransportErrorKind::Io => formatter.write_str("I/O failure"),
crate::TransportErrorKind::Protocol => formatter.write_str("protocol failure"),
crate::TransportErrorKind::Aborted => formatter.write_str("operation aborted"),
};
}
}
/// Transport-neutral operation failure with a stable category and diagnostic detail.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TransportError {
detail: String,
kind: crate::TransportErrorKind,
}
impl TransportError {
/// Creates a transport failure from a stable category and backend-neutral diagnostic detail.
#[must_use]
pub fn new(kind: crate::TransportErrorKind, detail: impl Into<String>) -> Self {
return Self { detail: detail.into(), kind };
}
/// Borrows the diagnostic detail associated with the failure.
#[must_use]
pub fn detail(&self) -> &str {
return self.detail.as_str();
}
/// Returns the stable transport-neutral failure category.
#[must_use]
pub fn kind(&self) -> crate::TransportErrorKind {
return self.kind;
}
}
impl core::fmt::Display for TransportError {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
return write!(formatter, "{}: {}", self.kind, self.detail);
}
}
impl std::error::Error for TransportError {}

View File

@@ -0,0 +1,31 @@
// file: crates/common/game-realtime-transport-lib/src/lib.rs
// version: 1
#![warn(missing_docs)]
#![deny(unreachable_pub)]
#![forbid(unsafe_code)]
//! Transport-neutral realtime connection contracts for games.sasedev.
mod connection;
mod error;
mod message;
/// Re-export of an established realtime connection that can be split into independent halves.
pub use self::connection::RealtimeConnection;
/// Re-export of the receive half of an established realtime connection.
pub use self::connection::RealtimeReceiver;
/// Re-export of the send half of an established realtime connection.
pub use self::connection::RealtimeSender;
/// Re-export of a transport-neutral operation failure.
pub use self::error::TransportError;
/// Re-export of transport-neutral error categories.
pub use self::error::TransportErrorKind;
/// Re-export of an owned opaque binary transport message.
pub use self::message::TransportMessage;
/// Re-export of the result of one receive operation.
pub use self::message::TransportReceive;
#[cfg(test)]
#[path = "../unit_tests/contract.rs"]
mod tests;

View File

@@ -0,0 +1,49 @@
// file: crates/common/game-realtime-transport-lib/src/message.rs
// version: 1
/// Owned opaque binary payload carried by a realtime transport.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TransportMessage {
bytes: Vec<u8>,
}
impl TransportMessage {
/// Creates a transport message from owned bytes.
#[must_use]
pub fn new(bytes: Vec<u8>) -> Self {
return Self { bytes };
}
/// Borrows the opaque payload bytes.
#[must_use]
pub fn as_bytes(&self) -> &[u8] {
return self.bytes.as_slice();
}
/// Consumes the message and returns its owned payload bytes.
#[must_use]
pub fn into_bytes(self) -> Vec<u8> {
return self.bytes;
}
/// Returns whether the payload is empty.
#[must_use]
pub fn is_empty(&self) -> bool {
return self.bytes.is_empty();
}
/// Returns the payload length in bytes.
#[must_use]
pub fn len(&self) -> usize {
return self.bytes.len();
}
}
/// Outcome of one successful transport receive operation.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum TransportReceive {
/// One opaque binary message was received.
Message(crate::TransportMessage),
/// The remote peer completed a clean transport-level close.
Closed,
}