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;
19
20pub use error::{DecodeError, EncodeError, LimitKind, SectionFramingError, WireResult};
21pub use header::{PacketFlags, PacketHeader, HEADER_SIZE, MAGIC, VERSION};
22pub use limits::Limits;
23pub use packet::{
24    decode_packet, encode_header, encode_section, SectionTag, WirePacket, WireSection,
25};
26
27#[cfg(test)]
28mod tests {
29    use super::*;
30    use std::mem::size_of;
31
32    #[test]
33    fn public_api_exports() {
34        // Verify all expected items are exported
35        let _ = MAGIC;
36        let _ = VERSION;
37        let _ = HEADER_SIZE;
38        let _ = PacketFlags::full_snapshot();
39        let _ = PacketHeader::full_snapshot(0, 0, 0);
40        let _ = Limits::default();
41        let _ = SectionTag::EntityCreate;
42
43        // Error types
44        let _: WireResult<()> = Ok(());
45    }
46
47    #[test]
48    fn limits_default_is_reasonable() {
49        let limits = Limits::default();
50        // Should be able to handle typical realtime scenarios
51        assert!(
52            limits.max_packet_bytes >= 1024,
53            "should allow at least 1KB packets"
54        );
55        assert!(
56            limits.max_section_len >= 512,
57            "should allow useful section sizes"
58        );
59    }
60
61    #[test]
62    fn header_size_constant_correct() {
63        // Sanity check the header size calculation
64        assert_eq!(
65            HEADER_SIZE,
66            size_of::<u32>() // magic
67                + size_of::<u16>() // version
68                + size_of::<u16>() // flags
69                + size_of::<u64>() // schema_hash
70                + size_of::<u32>() // tick
71                + size_of::<u32>() // baseline_tick
72                + size_of::<u32>() // payload_len
73        );
74    }
75
76    #[test]
77    fn packet_flags_and_header_integration() {
78        let flags = PacketFlags::delta_snapshot();
79        let header = PacketHeader::delta_snapshot(0x1234, 100, 95, 512);
80
81        assert_eq!(header.flags, flags);
82        assert!(header.flags.is_valid_v0());
83    }
84}