pub struct DMSCFrameParser { /* private fields */ }Expand description
Frame parser for reading and assembling protocol frames from stream data.
The DMSCFrameParser handles the incremental parsing of frame data from network streams or byte sources. Network protocols often deliver data in chunks that may not align with protocol frame boundaries. This parser accumulates incoming data in an internal buffer and extracts complete frames when sufficient data is available. It also manages sequence number validation to ensure frame ordering integrity.
§Parser Operation Model
Incoming Data: [partial][complete][partial][complete][partial]
| | | |
v v v v
Parser Buffer: [======][==========][=========][=======]
| | |
v v v
Extracted: [Frame1] [Frame2] [Frame3]§Sequence Number Validation
The parser maintains an expected sequence number counter. Each extracted frame
must have a sequence number matching the expected value. This detects missing
frames (gaps in sequence numbers) which may indicate packet loss. Use
reset_sequence() to set a new expected sequence number, such as after
reconnection.
§Buffer Management
The parser maintains an internal buffer that grows as data is added. For
long-running connections, periodically check buffer_len() and consider
calling clear_buffer() if buffer accumulation indicates parsing issues.
The parser automatically removes parsed data from the buffer.
§Python Bindings
When compiled with the pyo3 feature, this struct provides Python bindings:
from dmsc import DMSCFrameParser
# Create parser for incoming stream data
parser = DMSCFrameParser.new()
# Simulate receiving data chunks
chunks = [
frame1_bytes[:20],
frame1_bytes[20:] + frame2_bytes[:30],
frame2_bytes[30:] + frame3_bytes
]
for chunk in chunks:
parser.add_data(chunk)
while True:
frame = parser.parse_frame()
if frame is None:
break
print(f"Received frame: {frame.sequence_number()}")
print(f"Buffer contains {parser.buffer_len()} bytes")§Examples
Basic frame parsing from stream data:
use dmsc::protocol::frames::{DMSCFrameParser, DMSCFrame};
let mut parser = DMSCFrameParser::new();
// Simulate receiving frame data in chunks
let frame1 = DMSCFrame::data_frame(b"First message".to_vec(), 0)
.expect("Failed to create frame");
let frame2 = DMSCFrame::data_frame(b"Second message".to_vec(), 1)
.expect("Failed to create frame");
let bytes1 = frame1.to_bytes().expect("Failed to serialize");
let bytes2 = frame2.to_bytes().expect("Failed to serialize");
// Add first chunk (partial frame)
parser.add_data(&bytes1[..20]);
assert!(parser.parse_frame().unwrap().is_none());
// Add second chunk (completes frame1, starts frame2)
parser.add_data(&bytes1[20..]);
let parsed = parser.parse_frame().unwrap().expect("Should have complete frame");
assert_eq!(parsed.sequence_number(), 0);
// Add remaining data
parser.add_data(&bytes2);
let parsed = parser.parse_frame().unwrap().expect("Should have complete frame");
assert_eq!(parsed.sequence_number(), 1);Handling sequence number reset:
use dmsc::protocol::frames::DMSCFrameParser;
let mut parser = DMSCFrameParser::new();
// Parse some frames
parser.add_data(&some_data);
while let Ok(Some(frame)) = parser.parse_frame() {
// Process frames
}
// Reset sequence number for new session
parser.reset_sequence();
parser.clear_buffer();
// Now expecting sequence 0 again
assert_eq!(parser.next_sequence, 0);§Thread Safety
This struct is not thread-safe. Multiple threads should not concurrently access the same parser instance without external synchronization. For concurrent parsing, either use separate parser instances per thread or wrap access with a Mutex or RwLock.
§Performance Considerations
- The parser uses
Vec::extend_from_slicefor efficient buffer appending - Frame extraction uses slice operations to avoid unnecessary copying
- Buffer memory is only reclaimed when frames are successfully parsed
- Large frames may cause temporary buffer growth; configure appropriate limits
Implementations§
Source§impl DMSCFrameParser
impl DMSCFrameParser
pub fn new() -> Self
pub fn add_data(&mut self, data: &[u8])
pub fn parse_frame(&mut self) -> DMSCResult<Option<DMSCFrame>>
pub fn buffer_len(&self) -> usize
pub fn clear_buffer(&mut self)
pub fn reset_sequence(&mut self)
Trait Implementations§
Source§impl<'py> IntoPyObject<'py> for DMSCFrameParser
impl<'py> IntoPyObject<'py> for DMSCFrameParser
Source§type Target = DMSCFrameParser
type Target = DMSCFrameParser
Source§type Output = Bound<'py, <DMSCFrameParser as IntoPyObject<'py>>::Target>
type Output = Bound<'py, <DMSCFrameParser as IntoPyObject<'py>>::Target>
Source§fn into_pyobject(
self,
py: Python<'py>,
) -> Result<<Self as IntoPyObject<'_>>::Output, <Self as IntoPyObject<'_>>::Error>
fn into_pyobject( self, py: Python<'py>, ) -> Result<<Self as IntoPyObject<'_>>::Output, <Self as IntoPyObject<'_>>::Error>
Source§impl PyClass for DMSCFrameParser
impl PyClass for DMSCFrameParser
Source§impl PyClassImpl for DMSCFrameParser
impl PyClassImpl for DMSCFrameParser
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 = c"Frame parser for reading and assembling protocol frames from stream data.\n\nThe DMSCFrameParser handles the incremental parsing of frame data from network\nstreams or byte sources. Network protocols often deliver data in chunks that\nmay not align with protocol frame boundaries. This parser accumulates incoming\ndata in an internal buffer and extracts complete frames when sufficient data\nis available. It also manages sequence number validation to ensure frame\nordering integrity.\n\n## Parser Operation Model\n\n```\nIncoming Data: [partial][complete][partial][complete][partial]\n | | | |\n v v v v\nParser Buffer: [======][==========][=========][=======]\n | | |\n v v v\nExtracted: [Frame1] [Frame2] [Frame3]\n```\n\n## Sequence Number Validation\n\nThe parser maintains an expected sequence number counter. Each extracted frame\nmust have a sequence number matching the expected value. This detects missing\nframes (gaps in sequence numbers) which may indicate packet loss. Use\n`reset_sequence()` to set a new expected sequence number, such as after\nreconnection.\n\n## Buffer Management\n\nThe parser maintains an internal buffer that grows as data is added. For\nlong-running connections, periodically check `buffer_len()` and consider\ncalling `clear_buffer()` if buffer accumulation indicates parsing issues.\nThe parser automatically removes parsed data from the buffer.\n\n## Python Bindings\n\nWhen compiled with the `pyo3` feature, this struct provides Python bindings:\n```python\nfrom dmsc import DMSCFrameParser\n\n# Create parser for incoming stream data\nparser = DMSCFrameParser.new()\n\n# Simulate receiving data chunks\nchunks = [\n frame1_bytes[:20],\n frame1_bytes[20:] + frame2_bytes[:30],\n frame2_bytes[30:] + frame3_bytes\n]\n\nfor chunk in chunks:\n parser.add_data(chunk)\n while True:\n frame = parser.parse_frame()\n if frame is None:\n break\n print(f\"Received frame: {frame.sequence_number()}\")\n\nprint(f\"Buffer contains {parser.buffer_len()} bytes\")\n```\n\n# Examples\n\nBasic frame parsing from stream data:\n```rust,ignore\nuse dmsc::protocol::frames::{DMSCFrameParser, DMSCFrame};\n\nlet mut parser = DMSCFrameParser::new();\n\n// Simulate receiving frame data in chunks\nlet frame1 = DMSCFrame::data_frame(b\"First message\".to_vec(), 0)\n .expect(\"Failed to create frame\");\nlet frame2 = DMSCFrame::data_frame(b\"Second message\".to_vec(), 1)\n .expect(\"Failed to create frame\");\n\nlet bytes1 = frame1.to_bytes().expect(\"Failed to serialize\");\nlet bytes2 = frame2.to_bytes().expect(\"Failed to serialize\");\n\n// Add first chunk (partial frame)\nparser.add_data(&bytes1[..20]);\nassert!(parser.parse_frame().unwrap().is_none());\n\n// Add second chunk (completes frame1, starts frame2)\nparser.add_data(&bytes1[20..]);\nlet parsed = parser.parse_frame().unwrap().expect(\"Should have complete frame\");\nassert_eq!(parsed.sequence_number(), 0);\n\n// Add remaining data\nparser.add_data(&bytes2);\nlet parsed = parser.parse_frame().unwrap().expect(\"Should have complete frame\");\nassert_eq!(parsed.sequence_number(), 1);\n```\n\nHandling sequence number reset:\n```rust,ignore\nuse dmsc::protocol::frames::DMSCFrameParser;\n\nlet mut parser = DMSCFrameParser::new();\n\n// Parse some frames\nparser.add_data(&some_data);\nwhile let Ok(Some(frame)) = parser.parse_frame() {\n // Process frames\n}\n\n// Reset sequence number for new session\nparser.reset_sequence();\nparser.clear_buffer();\n\n// Now expecting sequence 0 again\nassert_eq!(parser.next_sequence, 0);\n```\n\n# Thread Safety\n\nThis struct is not thread-safe. Multiple threads should not concurrently\naccess the same parser instance without external synchronization. For\nconcurrent parsing, either use separate parser instances per thread or\nwrap access with a Mutex or RwLock.\n\n# Performance Considerations\n\n- The parser uses `Vec::extend_from_slice` for efficient buffer appending\n- Frame extraction uses slice operations to avoid unnecessary copying\n- Buffer memory is only reclaimed when frames are successfully parsed\n- Large frames may cause temporary buffer growth; configure appropriate limits\x00"
const RAW_DOC: &'static CStr = c"Frame parser for reading and assembling protocol frames from stream data.\n\nThe DMSCFrameParser handles the incremental parsing of frame data from network\nstreams or byte sources. Network protocols often deliver data in chunks that\nmay not align with protocol frame boundaries. This parser accumulates incoming\ndata in an internal buffer and extracts complete frames when sufficient data\nis available. It also manages sequence number validation to ensure frame\nordering integrity.\n\n## Parser Operation Model\n\n```\nIncoming Data: [partial][complete][partial][complete][partial]\n | | | |\n v v v v\nParser Buffer: [======][==========][=========][=======]\n | | |\n v v v\nExtracted: [Frame1] [Frame2] [Frame3]\n```\n\n## Sequence Number Validation\n\nThe parser maintains an expected sequence number counter. Each extracted frame\nmust have a sequence number matching the expected value. This detects missing\nframes (gaps in sequence numbers) which may indicate packet loss. Use\n`reset_sequence()` to set a new expected sequence number, such as after\nreconnection.\n\n## Buffer Management\n\nThe parser maintains an internal buffer that grows as data is added. For\nlong-running connections, periodically check `buffer_len()` and consider\ncalling `clear_buffer()` if buffer accumulation indicates parsing issues.\nThe parser automatically removes parsed data from the buffer.\n\n## Python Bindings\n\nWhen compiled with the `pyo3` feature, this struct provides Python bindings:\n```python\nfrom dmsc import DMSCFrameParser\n\n# Create parser for incoming stream data\nparser = DMSCFrameParser.new()\n\n# Simulate receiving data chunks\nchunks = [\n frame1_bytes[:20],\n frame1_bytes[20:] + frame2_bytes[:30],\n frame2_bytes[30:] + frame3_bytes\n]\n\nfor chunk in chunks:\n parser.add_data(chunk)\n while True:\n frame = parser.parse_frame()\n if frame is None:\n break\n print(f\"Received frame: {frame.sequence_number()}\")\n\nprint(f\"Buffer contains {parser.buffer_len()} bytes\")\n```\n\n# Examples\n\nBasic frame parsing from stream data:\n```rust,ignore\nuse dmsc::protocol::frames::{DMSCFrameParser, DMSCFrame};\n\nlet mut parser = DMSCFrameParser::new();\n\n// Simulate receiving frame data in chunks\nlet frame1 = DMSCFrame::data_frame(b\"First message\".to_vec(), 0)\n .expect(\"Failed to create frame\");\nlet frame2 = DMSCFrame::data_frame(b\"Second message\".to_vec(), 1)\n .expect(\"Failed to create frame\");\n\nlet bytes1 = frame1.to_bytes().expect(\"Failed to serialize\");\nlet bytes2 = frame2.to_bytes().expect(\"Failed to serialize\");\n\n// Add first chunk (partial frame)\nparser.add_data(&bytes1[..20]);\nassert!(parser.parse_frame().unwrap().is_none());\n\n// Add second chunk (completes frame1, starts frame2)\nparser.add_data(&bytes1[20..]);\nlet parsed = parser.parse_frame().unwrap().expect(\"Should have complete frame\");\nassert_eq!(parsed.sequence_number(), 0);\n\n// Add remaining data\nparser.add_data(&bytes2);\nlet parsed = parser.parse_frame().unwrap().expect(\"Should have complete frame\");\nassert_eq!(parsed.sequence_number(), 1);\n```\n\nHandling sequence number reset:\n```rust,ignore\nuse dmsc::protocol::frames::DMSCFrameParser;\n\nlet mut parser = DMSCFrameParser::new();\n\n// Parse some frames\nparser.add_data(&some_data);\nwhile let Ok(Some(frame)) = parser.parse_frame() {\n // Process frames\n}\n\n// Reset sequence number for new session\nparser.reset_sequence();\nparser.clear_buffer();\n\n// Now expecting sequence 0 again\nassert_eq!(parser.next_sequence, 0);\n```\n\n# Thread Safety\n\nThis struct is not thread-safe. Multiple threads should not concurrently\naccess the same parser instance without external synchronization. For\nconcurrent parsing, either use separate parser instances per thread or\nwrap access with a Mutex or RwLock.\n\n# Performance Considerations\n\n- The parser uses `Vec::extend_from_slice` for efficient buffer appending\n- Frame extraction uses slice operations to avoid unnecessary copying\n- Buffer memory is only reclaimed when frames are successfully parsed\n- Large frames may cause temporary buffer growth; configure appropriate limits\x00"
Source§const DOC: &'static CStr
const DOC: &'static CStr
text_signature if a constructor is defined. Read moreSource§type ThreadChecker = SendablePyClass<DMSCFrameParser>
type ThreadChecker = SendablePyClass<DMSCFrameParser>
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 DMSCFrameParser
impl PyTypeInfo for DMSCFrameParser
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 DMSCFrameParser
impl ExtractPyClassWithClone for DMSCFrameParser
Auto Trait Implementations§
impl Freeze for DMSCFrameParser
impl RefUnwindSafe for DMSCFrameParser
impl Send for DMSCFrameParser
impl Sync for DMSCFrameParser
impl Unpin for DMSCFrameParser
impl UnwindSafe for DMSCFrameParser
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
§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