Skip to main content

wire/
lib.rs

1//! Wire framing and packet layout for the sdec codec.
2//!
3//! This crate handles the binary wire format: packet headers, section framing,
4//! and limit enforcement. It does not know about game state types—only the
5//! structure of packets.
6//!
7//! # Design Principles
8//!
9//! - **Stable wire format** - The format is versioned and changes are documented.
10//! - **Bounded decoding** - All length fields are validated against limits before iteration.
11//! - **No domain knowledge** - This crate handles framing, not game logic.
12//!
13//! See `WIRE_FORMAT.md` for the complete specification.
14
15mod error;
16mod header;
17mod limits;
18mod packet;
19mod session;
20
21pub use error::{DecodeError, EncodeError, LimitKind, SectionFramingError, WireResult};
22pub use header::{PacketFlags, PacketHeader, HEADER_SIZE, MAGIC, VERSION};
23pub use limits::Limits;
24pub use packet::{
25    decode_packet, decode_sections, encode_header, encode_section, SectionTag, WirePacket,
26    WireSection,
27};
28pub use session::{
29    decode_session_header, encode_session_header, SessionFlags, SessionHeader,
30    SESSION_MAX_HEADER_SIZE,
31};
32
33#[cfg(test)]
34mod tests {
35    use super::*;
36    use std::mem::size_of;
37
38    #[test]
39    fn public_api_exports() {
40        // Verify all expected items are exported
41        let _ = MAGIC;
42        let _ = VERSION;
43        let _ = HEADER_SIZE;
44        let _ = PacketFlags::full_snapshot();
45        let _ = PacketHeader::full_snapshot(0, 0, 0);
46        let _ = Limits::default();
47        let _ = SectionTag::EntityCreate;
48        let _ = SessionFlags::full_snapshot();
49        let _ = SESSION_MAX_HEADER_SIZE;
50
51        // Error types
52        let _: WireResult<()> = Ok(());
53    }
54
55    #[test]
56    fn limits_default_is_reasonable() {
57        let limits = Limits::default();
58        // Should be able to handle typical realtime scenarios
59        assert!(
60            limits.max_packet_bytes >= 1024,
61            "should allow at least 1KB packets"
62        );
63        assert!(
64            limits.max_section_len >= 512,
65            "should allow useful section sizes"
66        );
67    }
68
69    #[test]
70    fn header_size_constant_correct() {
71        // Sanity check the header size calculation
72        assert_eq!(
73            HEADER_SIZE,
74            size_of::<u32>() // magic
75                + size_of::<u16>() // version
76                + size_of::<u16>() // flags
77                + size_of::<u64>() // schema_hash
78                + size_of::<u32>() // tick
79                + size_of::<u32>() // baseline_tick
80                + size_of::<u32>() // payload_len
81        );
82    }
83
84    #[test]
85    fn packet_flags_and_header_integration() {
86        let flags = PacketFlags::delta_snapshot();
87        let header = PacketHeader::delta_snapshot(0x1234, 100, 95, 512);
88
89        assert_eq!(header.flags, flags);
90        assert!(header.flags.is_valid_v0());
91    }
92}