dmsc/protocol/
frames.rs

1//! Copyright © 2025-2026 Wenze Wei. All Rights Reserved.
2//!
3//! This file is part of DMSC.
4//! The DMSC project belongs to the Dunimd Team.
5//!
6//! Licensed under the Apache License, Version 2.0 (the "License");
7//! You may not use this file except in compliance with the License.
8//! You may obtain a copy of the License at
9//!
10//!     http://www.apache.org/licenses/LICENSE-2.0
11//!
12//! Unless required by applicable law or agreed to in writing, software
13//! distributed under the License is distributed on an "AS IS" BASIS,
14//! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15//! See the License for the specific language governing permissions and
16//! limitations under the License.
17
18#![allow(non_snake_case)]
19
20//! # Protocol Frame Format Module
21//!
22//! This module implements the real protocol frame format with serialization,
23//! checksums, and frame integrity verification for the DMSC private protocol.
24
25use std::convert::TryInto;
26use serde::{Deserialize, Serialize};
27use crc32fast::Hasher;
28
29use crate::core::{DMSCResult, DMSCError};
30
31/// Protocol frame type enumeration defining the categories of protocol frames.
32///
33/// This enumeration classifies all protocol frames used in the DMSC protocol
34/// for network communication. Each frame type serves a specific purpose in
35/// the communication lifecycle, from initial connection establishment through
36/// data transmission, authentication, and connection maintenance. Frame type
37/// identification enables proper routing and processing of incoming frames
38/// by protocol handlers.
39///
40/// ## Frame Type Hierarchy
41///
42/// - **Control Frames (0x01)**: Protocol management and state transitions
43/// - **Data Frames (0x02)**: Application data payload transmission
44/// - **Auth Frames (0x03)**: Authentication and authorization exchanges
45/// - **Keep-Alive Frames (0x04)**: Connection liveness verification
46/// - **Error Frames (0x05)**: Error reporting and status communication
47/// - **Encrypted Frames (0x06)**: Pre-encrypted payload transmission
48///
49/// ## Frame Processing Guidelines
50///
51/// Protocol implementations should process frames in the following order:
52/// 1. First validate the frame header magic number and version
53/// 2. Extract and validate the frame type from the header
54/// 3. Route the frame to the appropriate handler based on frame type
55/// 4. Process the frame payload according to type-specific rules
56/// 5. Send appropriate response frames if required
57///
58/// ## Python Bindings
59///
60/// When compiled with the `pyo3` feature, this enum provides Python bindings
61/// for frame type identification:
62/// ```python
63/// from dmsc import DMSCFrameType
64///
65/// # Identify frame types for protocol handling
66/// control_type = DMSCFrameType.Control()
67/// data_type = DMSCFrameType.Data()
68/// auth_type = DMSCFrameType.Auth()
69///
70/// # Convert between types and byte values
71/// frame_type_value = DMSCFrameType.from_u8(0x01)
72/// byte_value = data_type.to_u8()  # Returns 0x02
73/// ```
74///
75/// ## Thread Safety
76///
77/// This enum is fully thread-safe and can be shared across concurrent contexts
78/// without additional synchronization. The Copy trait enables efficient passing
79/// of frame type values through function arguments and return types.
80///
81/// ## Storage and Transmission
82///
83/// Frame type values are stored as single bytes making them efficient for network
84/// transmission and compact storage. The Hash trait enables frame type usage as
85/// dictionary keys in collection types and provides efficient lookup performance.
86///
87/// # Examples
88///
89/// Basic frame type creation and conversion:
90/// ```rust,ignore
91/// use dmsc::protocol::frames::DMSCFrameType;
92///
93/// let control = DMSCFrameType::Control;
94/// let data = DMSCFrameType::Data;
95///
96/// assert_eq!(control as u8, 0x01);
97/// assert_eq!(data as u8, 0x02);
98/// assert_ne!(control, data);
99/// ```
100///
101/// Frame type matching in protocol handling:
102/// ```rust,ignore
103/// use dmsc::protocol::frames::DMSCFrameType;
104///
105/// fn handle_frame_type(frame_type: DMSCFrameType) -> &str {
106///     match frame_type {
107///         DMSCFrameType::Control => "Control frame - managing protocol state",
108///         DMSCFrameType::Data => "Data frame - processing payload",
109///         DMSCFrameType::Auth => "Auth frame - handling authentication",
110///         DMSCFrameType::KeepAlive => "Keep-alive frame - verifying connection",
111///         DMSCFrameType::Error => "Error frame - reporting error condition",
112///         DMSCFrameType::Encrypted => "Encrypted frame - processing secure payload",
113///     }
114/// }
115///
116/// assert_eq!(handle_frame_type(DMSCFrameType::Data), "Data frame - processing payload");
117/// ```
118///
119/// Converting between byte values and frame types:
120/// ```rust,ignore
121/// use dmsc::protocol::frames::DMSCFrameType;
122///
123/// // Convert byte to frame type
124/// let frame_type = DMSCFrameType::from_u8(0x03);
125/// assert_eq!(frame_type, Some(DMSCFrameType::Auth));
126///
127/// // Invalid byte value returns None
128/// let invalid = DMSCFrameType::from_u8(0xFF);
129/// assert_eq!(invalid, None);
130/// ```
131#[derive(Debug, Clone, Copy, PartialEq, Eq)]
132#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
133pub enum DMSCFrameType {
134    /// Control frame for protocol management operations.
135    ///
136    /// Control frames manage the protocol state machine and handle connection
137    /// lifecycle events. They are used for operations such as connection
138    /// initialization, version negotiation, feature flags exchange, and graceful
139    /// connection termination. Control frames must be processed before any data
140    /// frames to ensure proper protocol state establishment.
141    ///
142    /// ## Control Frame Payload Structure
143    ///
144    /// Control frame payloads contain a command identifier followed by
145    /// command-specific parameters encoded in a type-length-value (TLV) format.
146    ///
147    /// ## Common Control Commands
148    ///
149    /// - **Connection Request (0x01)**: Initiate new connection
150    /// - **Connection Ack (0x02)**: Confirm connection establishment
151    /// - **Disconnect Request (0x03)**: Initiate graceful disconnection
152    /// - **Ping (0x04)**: Request keep-alive response
153    /// - **Pong (0x05)**: Keep-alive response
154    /// - **Protocol Negotiation (0x10)**: Negotiate protocol features
155    Control = 0x01,
156
157    /// Data frame for application payload transmission.
158    ///
159    /// Data frames carry the primary application data through the protocol.
160    /// They are the most frequently used frame type in normal protocol operation
161    /// and support both streaming and message-based data transfer modes. Data
162    /// frames are sequenced and delivered in-order to ensure data integrity.
163    ///
164    /// ## Data Frame Characteristics
165    ///
166    /// - **Sequencing**: Each data frame has a unique sequence number
167    /// - **Ordering**: Frames are delivered in sequence number order
168    /// - **Flow Control**: Sliding window prevents buffer overflow
169    /// - **Aggregation**: Multiple small payloads can be aggregated
170    ///
171    /// ## Payload Considerations
172    ///
173    /// - Maximum payload size is defined by protocol configuration
174    /// - Large payloads may be fragmented across multiple frames
175    /// - Payload compression is available as an optional feature
176    Data = 0x02,
177
178    /// Authentication frame for credential exchange and verification.
179    ///
180    /// Authentication frames facilitate the authentication process between
181    /// communicating parties. They carry authentication tokens, certificates,
182    /// challenge-response pairs, and authentication results. All auth frames
183    /// are encrypted using the current session encryption keys.
184    ///
185    /// ## Authentication Flow
186    ///
187    /// 1. Client sends authentication request with credentials
188    /// 2. Server validates credentials and returns challenge
189    /// 3. Client responds to challenge with proof of possession
190    /// 4. Server confirms successful authentication
191    ///
192    /// ## Supported Authentication Methods
193    ///
194    /// - JWT token authentication
195    /// - Certificate-based mutual TLS
196    /// - Pre-shared key authentication
197    /// - OAuth 2.0 token exchange
198    Auth = 0x03,
199
200    /// Keep-alive frame for connection liveness verification.
201    ///
202    /// Keep-alive frames maintain connection vitality and detect unresponsive
203    /// peers. They are exchanged periodically between connected parties to
204    /// prevent connection timeout and detect connection failures. Keep-alive
205    /// frames have minimal overhead and contain no payload.
206    ///
207    KeepAlive = 0x04,
208
209    /// Error frame for error condition reporting.
210    ///
211    /// Error frames communicate error conditions from one protocol party to
212    /// another. They include an error code and human-readable error message
213    /// to facilitate debugging and error recovery. Error frames may be sent
214    /// in response to any invalid protocol message.
215    ///
216    Error = 0x05,
217
218    /// Encrypted frame for pre-encrypted payload transmission.
219    ///
220    /// Encrypted frames carry payloads that have been encrypted by the
221    /// application layer before being passed to the protocol. This allows
222    /// applications to use custom encryption schemes or to encrypt data
223    /// end-to-end between application endpoints. The protocol encrypts the
224    /// encrypted payload as normal data.
225    ///
226    /// ## Use Cases
227    ///
228    /// - End-to-end encrypted application data
229    /// - Custom encryption algorithm requirements
230    /// - Regulatory compliance requiring specific encryption
231    /// - Integration with external encryption systems
232    ///
233    /// ## Security Considerations
234    ///
235    /// When using encrypted frames, the outer protocol encryption provides
236    /// transport security while the inner encrypted payload provides
237    /// end-to-end security between application endpoints.
238    Encrypted = 0x06,
239}
240
241impl DMSCFrameType {
242    /// Convert from byte to frame type
243    pub fn from_u8(value: u8) -> Option<Self> {
244        match value {
245            0x01 => Some(DMSCFrameType::Control),
246            0x02 => Some(DMSCFrameType::Data),
247            0x03 => Some(DMSCFrameType::Auth),
248            0x04 => Some(DMSCFrameType::KeepAlive),
249            0x05 => Some(DMSCFrameType::Error),
250            0x06 => Some(DMSCFrameType::Encrypted),
251            _ => None,
252        }
253    }
254}
255
256/// Protocol frame header structure containing metadata for frame processing.
257///
258/// The frame header provides essential protocol metadata required for proper
259/// frame handling, transmission, and verification. It follows a fixed 32-byte
260/// format designed for efficient parsing and minimal overhead while maintaining
261/// comprehensive protocol information. All fields use big-endian byte ordering
262/// for consistent network transmission.
263///
264/// ## Header Field Layout
265///
266/// | Offset | Size | Field          | Description                              |
267/// |--------|------|----------------|------------------------------------------|
268/// | 0      | 4    | magic          | Protocol magic number (0x444D5350)       |
269/// | 4      | 1    | frame_type     | Frame type identifier (0x01-0x06)        |
270/// | 5      | 1    | version        | Protocol version (0x01)                  |
271/// | 6      | 2    | flags          | Protocol flags for special handling      |
272/// | 8      | 4    | payload_length | Length of frame payload in bytes         |
273/// | 12     | 4    | sequence_number| Frame sequence number for ordering       |
274/// | 16     | 8    | timestamp      | Unix timestamp of frame creation         |
275/// | 24     | 4    | checksum       | CRC32 checksum for integrity verification|
276///
277/// ## Byte Ordering
278///
279/// All multi-byte fields use big-endian (network byte order) encoding to ensure
280/// consistent interpretation across different architectures and platforms.
281/// When serializing or deserializing, use the provided `to_bytes()` and
282/// `from_bytes()` methods to ensure proper byte ordering.
283///
284/// ## Magic Number Validation
285///
286/// The magic number `0x444D5350` decodes to ASCII "DMSP" (DMSC Protocol) and
287/// serves as a quick validation that incoming data represents a valid DMSC
288/// frame. Receiving a frame with an invalid magic number indicates either
289/// protocol mismatch or data corruption.
290///
291/// ## Python Bindings
292///
293/// When compiled with the `pyo3` feature, this struct provides Python bindings:
294/// ```python
295/// from dmsc import DMSCFrameHeader
296///
297/// # Create new header for a data frame
298/// header = DMSCFrameHeader.new(
299///     frame_type=DMSCFrameHeader.FrameType.Data,
300///     payload_length=1024,
301///     sequence_number=42
302/// )
303///
304/// # Serialize to bytes for transmission
305/// header_bytes = header.to_bytes()
306///
307/// # Access header fields
308/// print(f"Frame type: {header.frame_type}")
309/// print(f"Payload length: {header.payload_length}")
310/// print(f"Sequence: {header.sequence_number}")
311/// print(f"Timestamp: {header.timestamp}")
312/// ```
313///
314/// # Examples
315///
316/// Creating a new frame header:
317/// ```rust,ignore
318/// use dmsc::protocol::frames::{DMSCFrameHeader, DMSCFrameType};
319///
320/// let header = DMSCFrameHeader::new(
321///     DMSCFrameType::Data,
322///     1024,           // payload length
323///     42              // sequence number
324/// ).expect("Failed to create frame header");
325///
326/// assert_eq!(header.magic, DMSCFrameHeader::MAGIC);
327/// assert_eq!(header.version, DMSCFrameHeader::VERSION);
328/// assert_eq!(header.frame_type, DMSCFrameType::Data as u8);
329/// ```
330///
331/// Serializing and deserializing headers:
332/// ```rust,ignore
333/// use dmsc::protocol::frames::{DMSCFrameHeader, DMSCFrameType};
334///
335/// let header = DMSCFrameHeader::new(
336///     DMSCFrameType::Control,
337///     256,
338///     100
339/// ).expect("Failed to create header");
340///
341/// let bytes = header.to_bytes();
342/// assert_eq!(bytes.len(), 32);
343///
344/// let reconstructed = DMSCFrameHeader::from_bytes(&bytes)
345///     .expect("Failed to parse header");
346///
347/// assert_eq!(header.magic, reconstructed.magic);
348/// assert_eq!(header.frame_type, reconstructed.frame_type);
349/// assert_eq!(header.sequence_number, reconstructed.sequence_number);
350/// ```
351///
352/// Verifying frame integrity:
353/// ```rust,ignore
354/// use dmsc::protocol::frames::{DMSCFrameHeader, DMSCFrameType};
355///
356/// let header = DMSCFrameHeader::new(
357///     DMSCFrameType::Data,
358///     512,
359///     200
360/// ).expect("Failed to create header");
361///
362/// let payload = b"This is the frame payload data";
363///
364/// let is_valid = header.verify_checksum(payload);
365/// assert!(is_valid);
366///
367/// // Modify payload and verify again
368/// let modified_payload = b"This payload has been modified!";
369/// let is_valid_modified = header.verify_checksum(modified_payload);
370/// assert!(!is_valid_modified);
371/// ```
372#[derive(Debug, Clone, Serialize, Deserialize)]
373#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
374pub struct DMSCFrameHeader {
375    /// Frame magic number identifying the DMSC protocol (4 bytes).
376    ///
377    /// The magic number is a 32-bit constant that uniquely identifies DMSC
378    /// protocol frames. It serves as a quick validation mechanism to detect
379    /// non-DMSC data or protocol version mismatches. The value 0x444D5350
380    /// corresponds to the ASCII encoding of "DMSP" (DMSC Protocol).
381    ///
382    /// ## Magic Number Details
383    ///
384    /// - **Value**: 0x444D5350
385    /// - **ASCII**: "DMSP"
386    /// - **Purpose**: Protocol identification
387    /// - **Validation**: Must match exactly on all received frames
388    ///
389    /// ## Usage
390    ///
391    /// The magic number is the first field in the frame header and should be
392    /// validated immediately upon receiving frame data. A mismatch indicates
393    /// either incorrect data or a protocol version incompatibility.
394    pub magic: u32,
395
396    /// Frame type identifier determining frame processing (1 byte).
397    ///
398    /// The frame type specifies how the frame payload should be interpreted
399    /// and processed. This 8-bit field identifies one of six possible frame
400    /// types defined in the DMSCFrameType enumeration.
401    pub frame_type: u8,
402
403    /// Protocol version for compatibility checking (1 byte).
404    ///
405    /// The version field enables protocol evolution while maintaining backward
406    /// compatibility. The current version is 0x01. Protocol implementations
407    /// should reject frames with unsupported versions.
408    pub version: u8,
409
410    /// Protocol flags for special frame handling (2 bytes).
411    ///
412    /// Flags provide additional processing instructions for frames. Common
413    /// flags include compression, priority, and streaming indicators.
414    ///
415    /// ## Flag Definitions
416    ///
417    /// - **Bit 0**: Compressed - Payload is compressed
418    /// - **Bit 1**: Priority - High priority frame
419    /// - **Bit 2**: Streaming - Part of streaming transfer
420    /// - **Bit 3**: Fragmented - Part of fragmented message
421    /// - **Bits 4-15**: Reserved for future use
422    pub flags: u16,
423
424    /// Length of the frame payload in bytes (4 bytes).
425    ///
426    /// This field specifies the exact number of bytes in the frame payload.
427    /// It enables proper memory allocation and bounds checking during frame
428    /// processing. The maximum payload length is 4GB.
429    pub payload_length: u32,
430
431    /// Frame sequence number for ordering and reliability (4 bytes).
432    ///
433    /// Sequence numbers enable in-order delivery, duplicate detection, and
434    /// loss detection for protocol frames. Each frame in a connection uses
435    /// a monotonically increasing sequence number with wraparound at 2^32.
436    ///
437    /// ## Sequence Number Semantics
438    ///
439    /// - **Initialization**: Sequence numbers start at 0 for new connections
440    /// - **Increment**: Each frame increments the sequence number by 1
441    /// - **Wraparound**: Sequence numbers wrap from 0xFFFFFFFF to 0
442    /// - **Ordering**: Receivers use sequence numbers to order frames
443    pub sequence_number: u32,
444
445    /// Unix timestamp of frame creation in seconds (8 bytes).
446    ///
447    /// The timestamp records when the frame was created, enabling temporal
448    /// validation, replay detection, and latency measurements. Timestamps
449    /// use seconds since Unix epoch (1970-01-01 00:00:00 UTC).
450    ///
451    /// ## Timestamp Considerations
452    ///
453    /// - **Precision**: Second-level precision (not milliseconds)
454    /// - **Clock Sync**: Requires loosely synchronized clocks
455    /// - **Replay Protection**: Used in conjunction with nonces
456    /// - **Age Limits**: Frames older than timeout are rejected
457    pub timestamp: u64,
458
459    /// CRC32 checksum for frame integrity verification (4 bytes).
460    ///
461    /// The checksum covers all header fields (except checksum itself) and
462    /// the complete frame payload. It enables detection of transmission
463    /// errors and data corruption. Uses the CRC32 algorithm with polynomial
464    /// 0x04C11DB7 (IEEE 802.3).
465    ///
466    /// ## Checksum Calculation
467    ///
468    /// The checksum is computed over the concatenation of all header fields
469    /// (excluding the checksum field) followed by the frame payload. This
470    /// provides comprehensive protection against single-bit errors and
471    /// many burst errors.
472    ///
473    /// ## Limitations
474    ///
475    /// CRC32 provides error detection but not error correction. It can detect
476    /// all single-bit errors, most double-bit errors, and many burst errors
477    /// up to 32 bits in length. It does not provide cryptographic integrity.
478    pub checksum: u32,
479}
480
481impl DMSCFrameHeader {
482    /// Frame magic number constant for protocol identification.
483    ///
484    /// This 32-bit constant uniquely identifies DMSC protocol frames. The value
485    /// 0x444D5350 corresponds to the ASCII encoding of "DMSP" (DMSC Protocol).
486    /// This magic number is placed at the beginning of every frame header and
487    /// is validated upon frame receipt to confirm protocol compatibility.
488    ///
489    /// ## Magic Number Details
490    ///
491    /// - **Hex Value**: 0x444D5350
492    /// - **ASCII Representation**: "DMSP"
493    /// - **Purpose**: Quick protocol identification
494    /// - **Validation**: Must match on all received frames
495    ///
496    /// ## Usage in Frame Processing
497    ///
498    /// When receiving frame data, the magic number should be validated first
499    /// before attempting to parse other header fields. A mismatch indicates:
500    ///
501    /// 1. The received data is not a DMSC frame
502    /// 2. Data corruption may have occurred
503    /// 3. The remote endpoint may be using a different protocol
504    pub const MAGIC: u32 = 0x444D5350; // "DMSCP" in ASCII
505    
506    /// Current protocol version identifier.
507    ///
508    /// This version number enables protocol evolution while maintaining backward
509    /// compatibility. The current version is 0x01. Future protocol enhancements
510    /// may increment this version while maintaining support for earlier versions.
511    ///
512    /// ## Version Semantics
513    ///
514    /// - **Major Version Changes**: May introduce incompatible changes
515    /// - **Minor Version Changes**: Backward-compatible enhancements
516    /// - **Current Value**: 0x01 (initial protocol version)
517    ///
518    /// ## Version Negotiation
519    ///
520    /// During connection establishment, endpoints should negotiate a compatible
521    /// protocol version. Frames with unsupported versions should be rejected
522    /// with an appropriate error response.
523    pub const VERSION: u8 = 0x01;
524    
525    /// Create a new frame header
526    pub fn new(frame_type: DMSCFrameType, payload_length: u32, sequence_number: u32) -> DMSCResult<Self> {
527        let timestamp = std::time::SystemTime::now()
528            .duration_since(std::time::UNIX_EPOCH)
529            .map_err(|e| DMSCError::InvalidState(format!("System time error: {}", e)))?
530            .as_secs();
531            
532        Ok(Self {
533            magic: Self::MAGIC,
534            frame_type: frame_type as u8,
535            version: Self::VERSION,
536            flags: 0,
537            payload_length,
538            sequence_number,
539            timestamp,
540            checksum: 0, // Will be calculated later
541        })
542    }
543    
544    /// Calculate CRC32 checksum for the header and payload
545    pub fn calculate_checksum(&self, payload: &[u8]) -> u32 {
546        let mut hasher = Hasher::new();
547        
548        // Add header fields (excluding checksum)
549        hasher.update(&self.magic.to_be_bytes());
550        hasher.update(&self.frame_type.to_be_bytes());
551        hasher.update(&self.version.to_be_bytes());
552        hasher.update(&self.flags.to_be_bytes());
553        hasher.update(&self.payload_length.to_be_bytes());
554        hasher.update(&self.sequence_number.to_be_bytes());
555        hasher.update(&self.timestamp.to_be_bytes());
556        
557        // Add payload
558        hasher.update(payload);
559        
560        hasher.finalize()
561    }
562    
563    /// Verify the checksum
564    pub fn verify_checksum(&self, payload: &[u8]) -> bool {
565        self.checksum == self.calculate_checksum(payload)
566    }
567    
568    /// Serialize header to bytes
569    pub fn to_bytes(&self) -> Vec<u8> {
570        let mut bytes = Vec::with_capacity(32);
571        
572        bytes.extend_from_slice(&self.magic.to_be_bytes());
573        bytes.extend_from_slice(&self.frame_type.to_be_bytes());
574        bytes.extend_from_slice(&self.version.to_be_bytes());
575        bytes.extend_from_slice(&self.flags.to_be_bytes());
576        bytes.extend_from_slice(&self.payload_length.to_be_bytes());
577        bytes.extend_from_slice(&self.sequence_number.to_be_bytes());
578        bytes.extend_from_slice(&self.timestamp.to_be_bytes());
579        bytes.extend_from_slice(&self.checksum.to_be_bytes());
580        
581        bytes
582    }
583    
584    /// Deserialize header from bytes
585    pub fn from_bytes(bytes: &[u8]) -> DMSCResult<Self> {
586        if bytes.len() < 32 {
587            return Err(DMSCError::FrameError("Invalid header length".to_string()));
588        }
589        
590        let magic = u32::from_be_bytes(bytes[0..4].try_into()
591            .map_err(|_| DMSCError::FrameError("Invalid magic number bytes".to_string()))?);
592        let frame_type = bytes[4];
593        let version = bytes[5];
594        let flags = u16::from_be_bytes(bytes[6..8].try_into()
595            .map_err(|_| DMSCError::FrameError("Invalid flags bytes".to_string()))?);
596        let payload_length = u32::from_be_bytes(bytes[8..12].try_into()
597            .map_err(|_| DMSCError::FrameError("Invalid payload length bytes".to_string()))?);
598        let sequence_number = u32::from_be_bytes(bytes[12..16].try_into()
599            .map_err(|_| DMSCError::FrameError("Invalid sequence number bytes".to_string()))?);
600        let timestamp = u64::from_be_bytes(bytes[16..24].try_into()
601            .map_err(|_| DMSCError::FrameError("Invalid timestamp bytes".to_string()))?);
602        let checksum = u32::from_be_bytes(bytes[24..28].try_into()
603            .map_err(|_| DMSCError::FrameError("Invalid checksum bytes".to_string()))?);
604        
605        Ok(Self {
606            magic,
607            frame_type,
608            version,
609            flags,
610            payload_length,
611            sequence_number,
612            timestamp,
613            checksum,
614        })
615    }
616}
617
618/// Complete protocol frame combining header and payload data.
619///
620/// A DMSCFrame represents the fundamental unit of data transmission in the
621/// DMSC protocol. Each frame consists of a fixed 32-byte header containing
622/// protocol metadata and a variable-length payload containing the actual
623/// application data. Frames are serialized for network transmission and
624/// deserialized upon receipt using CRC32 checksums for integrity verification.
625///
626/// ## Frame Structure
627///
628/// ```
629/// +------------------+-------------------+
630/// |   Header (32B)   |  Payload (VAR)    |
631/// +------------------+-------------------+
632/// | magic | type | v | flags | len | seq |
633/// |      timestamp     |    checksum     |
634/// +------------------+-------------------+
635/// ```
636///
637/// ## Frame Lifecycle
638///
639/// 1. **Creation**: Construct a frame using `new()` or one of the convenience
640///    constructors (`data_frame()`, `control_frame()`, etc.)
641/// 2. **Serialization**: Convert to bytes using `to_bytes()` for transmission
642/// 3. **Transmission**: Send bytes over the network connection
643/// 4. **Reception**: Receive bytes and add to frame parser buffer
644/// 5. **Deserialization**: Parse bytes back to frame using `from_bytes()`
645/// 6. **Processing**: Handle the frame based on its type
646///
647/// ## Frame Validity
648///
649/// A frame is considered valid when:
650/// - The magic number matches the DMSC protocol identifier
651/// - The protocol version is supported
652/// - The CRC32 checksum matches the computed checksum
653/// - The payload length matches the actual payload size
654///
655/// Use the `is_valid()` method for quick validation checking.
656///
657/// ## Python Bindings
658///
659/// When compiled with the `pyo3` feature, this struct provides Python bindings:
660/// ```python
661/// from dmsc import DMSCFrame, DMSCFrameType
662///
663/// # Create a data frame
664/// frame = DMSCFrame.data_frame(
665///     data=b"Hello, DMSC Protocol!",
666///     sequence_number=1
667/// )
668///
669/// # Serialize for transmission
670/// frame_bytes = frame.to_bytes()
671/// print(f"Frame size: {len(frame_bytes)} bytes")
672///
673/// # Access frame properties
674/// print(f"Frame type: {frame.frame_type()}")
675/// print(f"Sequence: {frame.sequence_number()}")
676/// print(f"Timestamp: {frame.timestamp()}")
677/// print(f"Valid: {frame.is_valid()}")
678///
679/// # Deserialize received frame
680/// received = DMSCFrame.from_bytes(frame_bytes)
681/// assert received.payload == b"Hello, DMSC Protocol!"
682/// ```
683///
684/// # Examples
685///
686/// Creating and serializing a data frame:
687/// ```rust,ignore
688/// use dmsc::protocol::frames::{DMSCFrame, DMSCFrameType};
689///
690/// let frame = DMSCFrame::data_frame(
691///     b"Hello, World!".to_vec(),
692///     42
693/// ).expect("Failed to create frame");
694///
695/// let bytes = frame.to_bytes().expect("Failed to serialize frame");
696/// println!("Frame serialized to {} bytes", bytes.len());
697///
698/// assert!(frame.is_valid());
699/// assert_eq!(frame.sequence_number(), 42);
700/// ```
701///
702/// Creating different frame types:
703/// ```rust,ignore
704/// use dmsc::protocol::frames::{DMSCFrame, DMSCFrameType};
705///
706/// // Control frame with command data
707/// let control = DMSCFrame::control_frame(
708///     vec![0x01, 0x02, 0x03],
709///     1
710/// ).expect("Failed to create control frame");
711///
712/// // Authentication frame with credentials
713/// let auth = DMSCFrame::auth_frame(
714///     b"token=abc123".to_vec(),
715///     2
716/// ).expect("Failed to create auth frame");
717///
718/// // Keep-alive frame (no payload)
719/// let keepalive = DMSCFrame::keepalive_frame(3)
720///     .expect("Failed to create keepalive frame");
721///
722/// // Error frame with code and message
723/// let error = DMSCFrame::error_frame(
724///     0x0401,
725///     "Connection timeout".to_string(),
726///     4
727/// ).expect("Failed to create error frame");
728/// ```
729///
730/// Receiving and deserializing frames:
731/// ```rust,ignore
732/// use dmsc::protocol::frames::{DMSCFrame, DMSCFrameType};
733///
734/// let original = DMSCFrame::data_frame(
735///     b"Received data".to_vec(),
736///     100
737/// ).expect("Failed to create frame");
738///
739/// let bytes = original.to_bytes().expect("Failed to serialize");
740///
741/// // Simulate network transmission
742/// let received = DMSCFrame::from_bytes(&bytes)
743///     .expect("Failed to deserialize frame");
744///
745/// assert_eq!(received.sequence_number(), 100);
746/// assert_eq!(received.payload, b"Received data");
747/// assert!(received.is_valid());
748/// ```
749#[derive(Debug, Clone)]
750#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
751pub struct DMSCFrame {
752    /// Frame header containing protocol metadata.
753    ///
754    /// The header provides essential information for frame processing including
755    /// the frame type, sequence number, timestamp, and integrity checksum.
756    /// It is always exactly 32 bytes in size and uses big-endian byte ordering.
757    pub header: DMSCFrameHeader,
758
759    /// Frame payload containing application data.
760    ///
761    /// The payload contains the actual data being transmitted. Its meaning
762    /// depends on the frame type:
763    /// - **Control**: Protocol management commands
764    /// - **Data**: Application-level message data
765    /// - **Auth**: Authentication credentials or tokens
766    /// - **KeepAlive**: Empty (no payload)
767    /// - **Error**: Error code + error message
768    /// - **Encrypted**: Pre-encrypted application data
769    pub payload: Vec<u8>,
770}
771
772impl DMSCFrame {
773    /// Create a new frame
774    pub fn new(frame_type: DMSCFrameType, payload: Vec<u8>, sequence_number: u32) -> DMSCResult<Self> {
775        let header = DMSCFrameHeader::new(frame_type, payload.len() as u32, sequence_number)?;
776        Ok(Self { header, payload })
777    }
778    
779    /// Create a control frame
780    pub fn control_frame(control_data: Vec<u8>, sequence_number: u32) -> DMSCResult<Self> {
781        Self::new(DMSCFrameType::Control, control_data, sequence_number)
782    }
783    
784    /// Create a data frame
785    pub fn data_frame(data: Vec<u8>, sequence_number: u32) -> DMSCResult<Self> {
786        Self::new(DMSCFrameType::Data, data, sequence_number)
787    }
788    
789    /// Create an authentication frame
790    pub fn auth_frame(auth_data: Vec<u8>, sequence_number: u32) -> DMSCResult<Self> {
791        Self::new(DMSCFrameType::Auth, auth_data, sequence_number)
792    }
793    
794    /// Create a keep-alive frame
795    pub fn keepalive_frame(sequence_number: u32) -> DMSCResult<Self> {
796        Self::new(DMSCFrameType::KeepAlive, vec![], sequence_number)
797    }
798    
799    /// Create an error frame
800    pub fn error_frame(error_code: u32, error_message: String, sequence_number: u32) -> DMSCResult<Self> {
801        let mut payload = Vec::new();
802        payload.extend_from_slice(&error_code.to_be_bytes());
803        payload.extend_from_slice(error_message.as_bytes());
804        Self::new(DMSCFrameType::Error, payload, sequence_number)
805    }
806    
807    /// Serialize frame to bytes
808    pub fn to_bytes(&self) -> DMSCResult<Vec<u8>> {
809        let mut header = self.header.clone();
810        
811        // Calculate and set checksum
812        header.checksum = header.calculate_checksum(&self.payload);
813        
814        let mut result = Vec::new();
815        result.extend_from_slice(&header.to_bytes());
816        result.extend_from_slice(&self.payload);
817        
818        Ok(result)
819    }
820    
821    /// Deserialize frame from bytes
822    pub fn from_bytes(bytes: &[u8]) -> DMSCResult<Self> {
823        if bytes.len() < 32 {
824            return Err(DMSCError::FrameError("Frame too short".to_string()));
825        }
826        
827        let header = DMSCFrameHeader::from_bytes(&bytes[0..32])?;
828        
829        // Verify magic number
830        if header.magic != DMSCFrameHeader::MAGIC {
831            return Err(DMSCError::FrameError(format!("Invalid magic number: 0x{:08X}", header.magic)));
832        }
833        
834        // Verify version
835        if header.version != DMSCFrameHeader::VERSION {
836            return Err(DMSCError::FrameError(format!("Unsupported version: {}", header.version)));
837        }
838        
839        // Check payload length
840        if bytes.len() < 32 + header.payload_length as usize {
841            return Err(DMSCError::FrameError("Incomplete frame".to_string()));
842        }
843        
844        let payload = bytes[32..32 + header.payload_length as usize].to_vec();
845        
846        // Verify checksum
847        if !header.verify_checksum(&payload) {
848            return Err(DMSCError::FrameError("Checksum verification failed".to_string()));
849        }
850        
851        Ok(Self { header, payload })
852    }
853    
854    /// Get frame type
855    pub fn frame_type(&self) -> Option<DMSCFrameType> {
856        DMSCFrameType::from_u8(self.header.frame_type)
857    }
858    
859    /// Get sequence number
860    pub fn sequence_number(&self) -> u32 {
861        self.header.sequence_number
862    }
863    
864    /// Get timestamp
865    pub fn timestamp(&self) -> u64 {
866        self.header.timestamp
867    }
868    
869    /// Check if frame is valid
870    pub fn is_valid(&self) -> bool {
871        self.header.magic == DMSCFrameHeader::MAGIC &&
872        self.header.version == DMSCFrameHeader::VERSION &&
873        self.header.verify_checksum(&self.payload)
874    }
875}
876
877/// Frame parser for reading and assembling protocol frames from stream data.
878///
879/// The DMSCFrameParser handles the incremental parsing of frame data from network
880/// streams or byte sources. Network protocols often deliver data in chunks that
881/// may not align with protocol frame boundaries. This parser accumulates incoming
882/// data in an internal buffer and extracts complete frames when sufficient data
883/// is available. It also manages sequence number validation to ensure frame
884/// ordering integrity.
885///
886/// ## Parser Operation Model
887///
888/// ```
889/// Incoming Data:  [partial][complete][partial][complete][partial]
890///                      |         |        |         |
891///                      v         v        v         v
892/// Parser Buffer:  [======][==========][=========][=======]
893///                      |         |        |
894///                      v         v        v
895/// Extracted:      [Frame1] [Frame2] [Frame3]
896/// ```
897///
898/// ## Sequence Number Validation
899///
900/// The parser maintains an expected sequence number counter. Each extracted frame
901/// must have a sequence number matching the expected value. This detects missing
902/// frames (gaps in sequence numbers) which may indicate packet loss. Use
903/// `reset_sequence()` to set a new expected sequence number, such as after
904/// reconnection.
905///
906/// ## Buffer Management
907///
908/// The parser maintains an internal buffer that grows as data is added. For
909/// long-running connections, periodically check `buffer_len()` and consider
910/// calling `clear_buffer()` if buffer accumulation indicates parsing issues.
911/// The parser automatically removes parsed data from the buffer.
912///
913/// ## Python Bindings
914///
915/// When compiled with the `pyo3` feature, this struct provides Python bindings:
916/// ```python
917/// from dmsc import DMSCFrameParser
918///
919/// # Create parser for incoming stream data
920/// parser = DMSCFrameParser.new()
921///
922/// # Simulate receiving data chunks
923/// chunks = [
924///     frame1_bytes[:20],
925///     frame1_bytes[20:] + frame2_bytes[:30],
926///     frame2_bytes[30:] + frame3_bytes
927/// ]
928///
929/// for chunk in chunks:
930///     parser.add_data(chunk)
931///     while True:
932///         frame = parser.parse_frame()
933///         if frame is None:
934///             break
935///         print(f"Received frame: {frame.sequence_number()}")
936///
937/// print(f"Buffer contains {parser.buffer_len()} bytes")
938/// ```
939///
940/// # Examples
941///
942/// Basic frame parsing from stream data:
943/// ```rust,ignore
944/// use dmsc::protocol::frames::{DMSCFrameParser, DMSCFrame};
945///
946/// let mut parser = DMSCFrameParser::new();
947///
948/// // Simulate receiving frame data in chunks
949/// let frame1 = DMSCFrame::data_frame(b"First message".to_vec(), 0)
950///     .expect("Failed to create frame");
951/// let frame2 = DMSCFrame::data_frame(b"Second message".to_vec(), 1)
952///     .expect("Failed to create frame");
953///
954/// let bytes1 = frame1.to_bytes().expect("Failed to serialize");
955/// let bytes2 = frame2.to_bytes().expect("Failed to serialize");
956///
957/// // Add first chunk (partial frame)
958/// parser.add_data(&bytes1[..20]);
959/// assert!(parser.parse_frame().unwrap().is_none());
960///
961/// // Add second chunk (completes frame1, starts frame2)
962/// parser.add_data(&bytes1[20..]);
963/// let parsed = parser.parse_frame().unwrap().expect("Should have complete frame");
964/// assert_eq!(parsed.sequence_number(), 0);
965///
966/// // Add remaining data
967/// parser.add_data(&bytes2);
968/// let parsed = parser.parse_frame().unwrap().expect("Should have complete frame");
969/// assert_eq!(parsed.sequence_number(), 1);
970/// ```
971///
972/// Handling sequence number reset:
973/// ```rust,ignore
974/// use dmsc::protocol::frames::DMSCFrameParser;
975///
976/// let mut parser = DMSCFrameParser::new();
977///
978/// // Parse some frames
979/// parser.add_data(&some_data);
980/// while let Ok(Some(frame)) = parser.parse_frame() {
981///     // Process frames
982/// }
983///
984/// // Reset sequence number for new session
985/// parser.reset_sequence();
986/// parser.clear_buffer();
987///
988/// // Now expecting sequence 0 again
989/// assert_eq!(parser.next_sequence, 0);
990/// ```
991///
992/// # Thread Safety
993///
994/// This struct is not thread-safe. Multiple threads should not concurrently
995/// access the same parser instance without external synchronization. For
996/// concurrent parsing, either use separate parser instances per thread or
997/// wrap access with a Mutex or RwLock.
998///
999/// # Performance Considerations
1000///
1001/// - The parser uses `Vec::extend_from_slice` for efficient buffer appending
1002/// - Frame extraction uses slice operations to avoid unnecessary copying
1003/// - Buffer memory is only reclaimed when frames are successfully parsed
1004/// - Large frames may cause temporary buffer growth; configure appropriate limits
1005#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
1006pub struct DMSCFrameParser {
1007    /// Internal buffer for accumulating incoming data.
1008    ///
1009    /// The buffer holds bytes that have been received but not yet assembled
1010    /// into complete frames. It grows dynamically as more data arrives.
1011    /// Data is automatically removed from the buffer once successfully parsed.
1012    buffer: Vec<u8>,
1013
1014    /// Next expected sequence number for validation.
1015    ///
1016    /// This counter tracks the sequence number of the next frame expected
1017    /// from the stream. Frames with mismatching sequence numbers indicate
1018    /// potential packet loss or protocol errors.
1019    next_sequence: u32,
1020}
1021
1022impl DMSCFrameParser {
1023    pub fn new() -> Self {
1024        Self {
1025            buffer: Vec::new(),
1026            next_sequence: 0,
1027        }
1028    }
1029    
1030    pub fn add_data(&mut self, data: &[u8]) {
1031        self.buffer.extend_from_slice(data);
1032    }
1033    
1034    pub fn parse_frame(&mut self) -> DMSCResult<Option<DMSCFrame>> {
1035        if self.buffer.len() < 32 {
1036            return Ok(None);
1037        }
1038        
1039        let header = DMSCFrameHeader::from_bytes(&self.buffer[0..32])?;
1040        let total_length = 32 + header.payload_length as usize;
1041        
1042        if self.buffer.len() < total_length {
1043            return Ok(None);
1044        }
1045        
1046        let frame_bytes = self.buffer[0..total_length].to_vec();
1047        let frame = DMSCFrame::from_bytes(&frame_bytes)?;
1048        
1049        if frame.header.sequence_number != self.next_sequence {
1050            return Ok(None);
1051        }
1052        
1053        self.buffer.drain(0..total_length);
1054        self.next_sequence = self.next_sequence.wrapping_add(1);
1055        
1056        Ok(Some(frame))
1057    }
1058    
1059    pub fn buffer_len(&self) -> usize {
1060        self.buffer.len()
1061    }
1062    
1063    pub fn clear_buffer(&mut self) {
1064        self.buffer.clear();
1065    }
1066    
1067    pub fn reset_sequence(&mut self) {
1068        self.next_sequence = 0;
1069    }
1070}
1071
1072/// Frame builder for creating protocol frames with automatic sequence numbering.
1073///
1074/// The DMSCFrameBuilder provides a convenient interface for constructing DMSC frames
1075/// while automatically managing sequence numbers. Rather than manually tracking and
1076/// incrementing sequence numbers for each frame, the builder maintains an internal
1077/// counter that is automatically incremented after each frame construction. This
1078/// ensures proper sequence numbering without the risk of human error.
1079///
1080/// ## Builder Pattern Advantages
1081///
1082/// Using the frame builder provides several benefits over direct frame construction:
1083///
1084/// - **Automatic Sequencing**: No need to manually track and increment sequence numbers
1085/// - **Type Safety**: Compile-time checking of frame type construction
1086/// - **Convenience Methods**: Domain-specific constructors for each frame type
1087/// - **State Management**: Builder maintains state across frame constructions
1088///
1089/// ## Sequence Number Management
1090///
1091/// The builder maintains an internal sequence counter that is automatically incremented
1092/// after each frame construction. The counter uses wrapping arithmetic (modulo 2^32)
1093/// to handle overflow gracefully. You can query or set the current sequence number
1094/// using `next_sequence()` and `set_sequence()` methods.
1095///
1096/// ## Python Bindings
1097///
1098/// When compiled with the `pyo3` feature, this struct provides Python bindings:
1099/// ```python
1100/// from dmsc import DMSCFrameBuilder
1101///
1102/// # Create builder for convenient frame construction
1103/// builder = DMSCFrameBuilder.new()
1104///
1105/// # Build frames without manually tracking sequence numbers
1106/// control_frame = builder.build_control_frame(b"\x01\x02\x03")
1107/// data_frame = builder.build_data_frame(b"Hello, World!")
1108/// auth_frame = builder.build_auth_frame(b"token=abc123")
1109///
1110/// # Check current sequence number
1111/// print(f"Next sequence: {builder.next_sequence()}")
1112///
1113/// # Reset sequence for new session
1114/// builder.set_sequence(0)
1115/// ```
1116///
1117/// # Examples
1118///
1119/// Building multiple frames with automatic sequencing:
1120/// ```rust,ignore
1121/// use dmsc::protocol::frames::DMSCFrameBuilder;
1122///
1123/// let mut builder = DMSCFrameBuilder::new();
1124///
1125/// // Build a series of data frames
1126/// let frame1 = builder.build_data_frame(b"Message 1".to_vec())
1127///     .expect("Failed to build frame");
1128/// let frame2 = builder.build_data_frame(b"Message 2".to_vec())
1129///     .expect("Failed to build frame");
1130/// let frame3 = builder.build_data_frame(b"Message 3".to_vec())
1131///     .expect("Failed to build frame");
1132///
1133/// assert_eq!(frame1.sequence_number(), 0);
1134/// assert_eq!(frame2.sequence_number(), 1);
1135/// assert_eq!(frame3.sequence_number(), 2);
1136///
1137/// // Current sequence is now 3
1138/// assert_eq!(builder.next_sequence(), 3);
1139/// ```
1140///
1141/// Building different frame types:
1142/// ```rust,ignore
1143/// use dmsc::protocol::frames::DMSCFrameBuilder;
1144///
1145/// let mut builder = DMSCFrameBuilder::new();
1146///
1147/// // Control frame
1148/// let control = builder.build_control_frame(vec![0x01, 0x00, 0x01])
1149///     .expect("Failed to build control frame");
1150///
1151/// // Authentication frame
1152/// let auth = builder.build_auth_frame(b"credentials=secret".to_vec())
1153///     .expect("Failed to build auth frame");
1154///
1155/// // Keep-alive frame
1156/// let keepalive = builder.build_keepalive_frame()
1157///     .expect("Failed to build keepalive frame");
1158///
1159/// // Error frame
1160/// let error = builder.build_error_frame(0x0401, "Timeout".to_string())
1161///     .expect("Failed to build error frame");
1162/// ```
1163///
1164/// Managing sequence numbers:
1165/// ```rust,ignore
1166/// use dmsc::protocol::frames::DMSCFrameBuilder;
1167///
1168/// let mut builder = DMSCFrameBuilder::new();
1169///
1170/// // Build some frames
1171/// let _ = builder.build_data_frame(b"Frame 0".to_vec()).unwrap();
1172/// let _ = builder.build_data_frame(b"Frame 1".to_vec()).unwrap();
1173/// let _ = builder.build_data_frame(b"Frame 2".to_vec()).unwrap();
1174///
1175/// // Check current sequence
1176/// assert_eq!(builder.next_sequence(), 3);
1177///
1178/// // Set specific sequence for resend or new session
1179/// builder.set_sequence(100);
1180///
1181/// let next = builder.build_data_frame(b"Frame 100".to_vec()).unwrap();
1182/// assert_eq!(next.sequence_number(), 100);
1183/// assert_eq!(builder.next_sequence(), 101);
1184/// ```
1185///
1186/// # Thread Safety
1187///
1188/// This struct is not thread-safe. Multiple threads should not concurrently
1189/// access the same builder instance without external synchronization. For
1190/// concurrent frame building, either use separate builder instances per thread
1191/// or wrap access with a Mutex or RwLock.
1192///
1193/// # Performance Characteristics
1194///
1195/// - Frame construction is O(1) for fixed-size headers
1196/// - Payload copying is O(n) where n is payload size
1197/// - Sequence number operations are O(1)
1198/// - Minimal heap allocation for small payloads
1199#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
1200pub struct DMSCFrameBuilder {
1201    /// Internal counter for automatic sequence number generation.
1202    ///
1203    /// This counter tracks the sequence number to assign to the next frame
1204    /// constructed by the builder. It is automatically incremented after
1205    /// each frame construction using wrapping arithmetic.
1206    next_sequence: u32,
1207}
1208
1209impl DMSCFrameBuilder {
1210    pub fn new() -> Self {
1211        Self { next_sequence: 0 }
1212    }
1213    
1214    pub fn build_control_frame(&mut self, control_data: Vec<u8>) -> DMSCResult<DMSCFrame> {
1215        let frame = DMSCFrame::control_frame(control_data, self.next_sequence)?;
1216        self.next_sequence = self.next_sequence.wrapping_add(1);
1217        Ok(frame)
1218    }
1219    
1220    pub fn build_data_frame(&mut self, data: Vec<u8>) -> DMSCResult<DMSCFrame> {
1221        let frame = DMSCFrame::data_frame(data, self.next_sequence)?;
1222        self.next_sequence = self.next_sequence.wrapping_add(1);
1223        Ok(frame)
1224    }
1225    
1226    pub fn build_auth_frame(&mut self, auth_data: Vec<u8>) -> DMSCResult<DMSCFrame> {
1227        let frame = DMSCFrame::auth_frame(auth_data, self.next_sequence)?;
1228        self.next_sequence = self.next_sequence.wrapping_add(1);
1229        Ok(frame)
1230    }
1231    
1232    pub fn build_keepalive_frame(&mut self) -> DMSCResult<DMSCFrame> {
1233        let frame = DMSCFrame::keepalive_frame(self.next_sequence)?;
1234        self.next_sequence = self.next_sequence.wrapping_add(1);
1235        Ok(frame)
1236    }
1237    
1238    pub fn build_error_frame(&mut self, error_code: u32, error_message: String) -> DMSCResult<DMSCFrame> {
1239        let frame = DMSCFrame::error_frame(error_code, error_message, self.next_sequence)?;
1240        self.next_sequence = self.next_sequence.wrapping_add(1);
1241        Ok(frame)
1242    }
1243    
1244    pub fn next_sequence(&self) -> u32 {
1245        self.next_sequence
1246    }
1247    
1248    pub fn set_sequence(&mut self, sequence: u32) {
1249        self.next_sequence = sequence;
1250    }
1251}
1252
1253