pub struct RiFrame {
pub header: RiFrameHeader,
pub payload: Vec<u8>,
}Expand description
Complete protocol frame combining header and payload data.
A RiFrame represents the fundamental unit of data transmission in the Ri protocol. Each frame consists of a fixed 32-byte header containing protocol metadata and a variable-length payload containing the actual application data. Frames are serialized for network transmission and deserialized upon receipt using CRC32 checksums for integrity verification.
§Frame Structure
+------------------+-------------------+
| Header (32B) | Payload (VAR) |
+------------------+-------------------+
| magic | type | v | flags | len | seq |
| timestamp | checksum |
+------------------+-------------------+§Frame Lifecycle
- Creation: Construct a frame using
new()or one of the convenience constructors (data_frame(),control_frame(), etc.) - Serialization: Convert to bytes using
to_bytes()for transmission - Transmission: Send bytes over the network connection
- Reception: Receive bytes and add to frame parser buffer
- Deserialization: Parse bytes back to frame using
from_bytes() - Processing: Handle the frame based on its type
§Frame Validity
A frame is considered valid when:
- The magic number matches the Ri protocol identifier
- The protocol version is supported
- The CRC32 checksum matches the computed checksum
- The payload length matches the actual payload size
Use the is_valid() method for quick validation checking.
§Python Bindings
When compiled with the pyo3 feature, this struct provides Python bindings:
from ri import RiFrame, RiFrameType
# Create a data frame
frame = RiFrame.data_frame(
data=b"Hello, Ri Protocol!",
sequence_number=1
)
# Serialize for transmission
frame_bytes = frame.to_bytes()
print(f"Frame size: {len(frame_bytes)} bytes")
# Access frame properties
print(f"Frame type: {frame.frame_type()}")
print(f"Sequence: {frame.sequence_number()}")
print(f"Timestamp: {frame.timestamp()}")
print(f"Valid: {frame.is_valid()}")
# Deserialize received frame
received = RiFrame.from_bytes(frame_bytes)
assert received.payload == b"Hello, Ri Protocol!"§Examples
Creating and serializing a data frame:
use ri::protocol::frames::{RiFrame, RiFrameType};
let frame = RiFrame::data_frame(
b"Hello, World!".to_vec(),
42
).expect("Failed to create frame");
let bytes = frame.to_bytes().expect("Failed to serialize frame");
println!("Frame serialized to {} bytes", bytes.len());
assert!(frame.is_valid());
assert_eq!(frame.sequence_number(), 42);Creating different frame types:
use ri::protocol::frames::{RiFrame, RiFrameType};
// Control frame with command data
let control = RiFrame::control_frame(
vec![0x01, 0x02, 0x03],
1
).expect("Failed to create control frame");
// Authentication frame with credentials
let auth = RiFrame::auth_frame(
b"token=abc123".to_vec(),
2
).expect("Failed to create auth frame");
// Keep-alive frame (no payload)
let keepalive = RiFrame::keepalive_frame(3)
.expect("Failed to create keepalive frame");
// Error frame with code and message
let error = RiFrame::error_frame(
0x0401,
"Connection timeout".to_string(),
4
).expect("Failed to create error frame");Receiving and deserializing frames:
use ri::protocol::frames::{RiFrame, RiFrameType};
let original = RiFrame::data_frame(
b"Received data".to_vec(),
100
).expect("Failed to create frame");
let bytes = original.to_bytes().expect("Failed to serialize");
// Simulate network transmission
let received = RiFrame::from_bytes(&bytes)
.expect("Failed to deserialize frame");
assert_eq!(received.sequence_number(), 100);
assert_eq!(received.payload, b"Received data");
assert!(received.is_valid());Fields§
§header: RiFrameHeaderFrame header containing protocol metadata.
The header provides essential information for frame processing including the frame type, sequence number, timestamp, and integrity checksum. It is always exactly 32 bytes in size and uses big-endian byte ordering.
payload: Vec<u8>Frame payload containing application data.
The payload contains the actual data being transmitted. Its meaning depends on the frame type:
- Control: Protocol management commands
- Data: Application-level message data
- Auth: Authentication credentials or tokens
- KeepAlive: Empty (no payload)
- Error: Error code + error message
- Encrypted: Pre-encrypted application data
Implementations§
Source§impl RiFrame
impl RiFrame
Sourcepub fn new(
frame_type: RiFrameType,
payload: Vec<u8>,
sequence_number: u32,
) -> RiResult<Self>
pub fn new( frame_type: RiFrameType, payload: Vec<u8>, sequence_number: u32, ) -> RiResult<Self>
Create a new frame
Sourcepub fn control_frame(
control_data: Vec<u8>,
sequence_number: u32,
) -> RiResult<Self>
pub fn control_frame( control_data: Vec<u8>, sequence_number: u32, ) -> RiResult<Self>
Create a control frame
Sourcepub fn auth_frame(auth_data: Vec<u8>, sequence_number: u32) -> RiResult<Self>
pub fn auth_frame(auth_data: Vec<u8>, sequence_number: u32) -> RiResult<Self>
Create an authentication frame
Sourcepub fn keepalive_frame(sequence_number: u32) -> RiResult<Self>
pub fn keepalive_frame(sequence_number: u32) -> RiResult<Self>
Create a keep-alive frame
Sourcepub fn error_frame(
error_code: u32,
error_message: String,
sequence_number: u32,
) -> RiResult<Self>
pub fn error_frame( error_code: u32, error_message: String, sequence_number: u32, ) -> RiResult<Self>
Create an error frame
Sourcepub fn from_bytes(bytes: &[u8]) -> RiResult<Self>
pub fn from_bytes(bytes: &[u8]) -> RiResult<Self>
Deserialize frame from bytes
Sourcepub fn frame_type(&self) -> Option<RiFrameType>
pub fn frame_type(&self) -> Option<RiFrameType>
Get frame type
Sourcepub fn sequence_number(&self) -> u32
pub fn sequence_number(&self) -> u32
Get sequence number
Trait Implementations§
Source§impl<'py> IntoPyObject<'py> for RiFrame
impl<'py> IntoPyObject<'py> for RiFrame
Source§impl PyClassImpl for RiFrame
impl PyClassImpl for RiFrame
Source§const IS_BASETYPE: bool = false
const IS_BASETYPE: bool = false
Source§const IS_SUBCLASS: bool = false
const IS_SUBCLASS: bool = false
Source§const IS_MAPPING: bool = false
const IS_MAPPING: bool = false
Source§const IS_SEQUENCE: bool = false
const IS_SEQUENCE: bool = false
Source§const IS_IMMUTABLE_TYPE: bool = false
const IS_IMMUTABLE_TYPE: bool = false
Source§const RAW_DOC: &'static CStr = /// ```
const RAW_DOC: &'static CStr = /// ```
Source§const DOC: &'static CStr
const DOC: &'static CStr
text_signature if a constructor is defined. Read moreSource§type ThreadChecker = SendablePyClass<RiFrame>
type ThreadChecker = SendablePyClass<RiFrame>
Source§type PyClassMutability = <<PyAny as PyClassBaseType>::PyClassMutability as PyClassMutability>::MutableChild
type PyClassMutability = <<PyAny as PyClassBaseType>::PyClassMutability as PyClassMutability>::MutableChild
Source§type BaseNativeType = PyAny
type BaseNativeType = PyAny
PyAny by default, and when you declare
#[pyclass(extends=PyDict)], it’s PyDict.fn items_iter() -> PyClassItemsIter
fn lazy_type_object() -> &'static LazyTypeObject<Self>
fn dict_offset() -> Option<isize>
fn weaklist_offset() -> Option<isize>
Source§impl PyTypeInfo for RiFrame
impl PyTypeInfo for RiFrame
Source§fn type_object_raw(py: Python<'_>) -> *mut PyTypeObject
fn type_object_raw(py: Python<'_>) -> *mut PyTypeObject
§fn type_object(py: Python<'_>) -> Bound<'_, PyType>
fn type_object(py: Python<'_>) -> Bound<'_, PyType>
§fn is_type_of(object: &Bound<'_, PyAny>) -> bool
fn is_type_of(object: &Bound<'_, PyAny>) -> bool
object is an instance of this type or a subclass of this type.§fn is_exact_type_of(object: &Bound<'_, PyAny>) -> bool
fn is_exact_type_of(object: &Bound<'_, PyAny>) -> bool
object is an instance of this type.impl DerefToPyAny for RiFrame
impl ExtractPyClassWithClone for RiFrame
Auto Trait Implementations§
impl Freeze for RiFrame
impl RefUnwindSafe for RiFrame
impl Send for RiFrame
impl Sync for RiFrame
impl Unpin for RiFrame
impl UnsafeUnpin for RiFrame
impl UnwindSafe for RiFrame
Blanket Implementations§
§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<'py, T> IntoPyObjectExt<'py> for Twhere
T: IntoPyObject<'py>,
impl<'py, T> IntoPyObjectExt<'py> for Twhere
T: IntoPyObject<'py>,
§fn into_bound_py_any(self, py: Python<'py>) -> Result<Bound<'py, PyAny>, PyErr>
fn into_bound_py_any(self, py: Python<'py>) -> Result<Bound<'py, PyAny>, PyErr>
self into an owned Python object, dropping type information.§fn into_py_any(self, py: Python<'py>) -> Result<Py<PyAny>, PyErr>
fn into_py_any(self, py: Python<'py>) -> Result<Py<PyAny>, PyErr>
self into an owned Python object, dropping type information and unbinding it
from the 'py lifetime.§fn into_pyobject_or_pyerr(self, py: Python<'py>) -> Result<Self::Output, PyErr>
fn into_pyobject_or_pyerr(self, py: Python<'py>) -> Result<Self::Output, PyErr>
self into a Python object. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::RequestSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> PyErrArguments for T
impl<T> PyErrArguments for T
§impl<T> PyTypeCheck for Twhere
T: PyTypeInfo,
impl<T> PyTypeCheck for Twhere
T: PyTypeInfo,
§const NAME: &'static str = T::NAME
const NAME: &'static str = T::NAME
§fn type_check(object: &Bound<'_, PyAny>) -> bool
fn type_check(object: &Bound<'_, PyAny>) -> bool
§fn classinfo_object(py: Python<'_>) -> Bound<'_, PyAny>
fn classinfo_object(py: Python<'_>) -> Bound<'_, PyAny>
isinstance and issubclass function. Read more