cursor_usage/
cursor_usage.rs

1//! Example demonstrating the use of `Byteable` with `std::io::Cursor`.
2//!
3//! This example shows how to work with in-memory buffers using Cursor,
4//! which is useful for network protocols, packet parsing, and testing.
5
6use byteable::{BigEndian, Byteable, LittleEndian, ReadByteable, WriteByteable};
7use std::io::Cursor;
8
9/// A simple message header for a network protocol
10#[derive(Byteable, Clone, Copy, PartialEq, Debug)]
11#[repr(C, packed)]
12struct MessageHeader {
13    magic: [u8; 4],                     // Protocol magic number
14    version: u8,                        // Protocol version
15    message_type: u8,                   // Message type identifier
16    payload_length: BigEndian<u16>,     // Length of payload in bytes
17    sequence_number: LittleEndian<u32>, // Message sequence number
18}
19
20/// A login request message
21#[derive(Byteable, Clone, Copy, PartialEq, Debug)]
22#[repr(C, packed)]
23struct LoginRequest {
24    user_id: LittleEndian<u32>,
25    session_token: LittleEndian<u64>,
26    flags: u8,
27    padding: [u8; 3], // Padding for alignment
28}
29
30/// A status response message
31#[derive(Byteable, Clone, Copy, PartialEq, Debug)]
32#[repr(C, packed)]
33struct StatusResponse {
34    status_code: BigEndian<u16>,
35    timestamp: LittleEndian<u64>,
36    reserved: [u8; 6],
37}
38
39fn main() -> std::io::Result<()> {
40    println!("=== Cursor-based Byteable Example ===\n");
41
42    // Example 1: Writing to a cursor (in-memory buffer)
43    println!("1. Writing messages to an in-memory buffer:");
44
45    let header = MessageHeader {
46        magic: *b"DEMO",
47        version: 1,
48        message_type: 0x01,
49        payload_length: BigEndian::new(16),
50        sequence_number: LittleEndian::new(1001),
51    };
52
53    let login = LoginRequest {
54        user_id: LittleEndian::new(42),
55        session_token: LittleEndian::new(0x1234567890ABCDEF),
56        flags: 0b00001111,
57        padding: [0; 3],
58    };
59
60    // Write to cursor
61    let mut buffer = Cursor::new(Vec::new());
62    buffer.write_one(header)?;
63    buffer.write_one(login)?;
64
65    let bytes = buffer.into_inner();
66    println!("   Written {} bytes", bytes.len());
67    println!("   Buffer contents: {:02X?}\n", bytes);
68
69    // Example 2: Reading from a cursor
70    println!("2. Reading messages from the buffer:");
71    let mut reader = Cursor::new(bytes.clone());
72
73    let read_header: MessageHeader = reader.read_one()?;
74    let read_login: LoginRequest = reader.read_one()?;
75
76    println!("   Header:");
77    println!(
78        "      Magic: {}",
79        std::str::from_utf8(&read_header.magic).unwrap_or("???")
80    );
81    println!("      Version: {}", read_header.version);
82    println!("      Message Type: 0x{:02X}", read_header.message_type);
83    println!(
84        "      Payload Length: {} bytes",
85        read_header.payload_length.get()
86    );
87    println!(
88        "      Sequence Number: {}",
89        read_header.sequence_number.get()
90    );
91
92    println!("\n   Login Request:");
93    println!("      User ID: {}", read_login.user_id.get());
94    println!(
95        "      Session Token: 0x{:016X}",
96        read_login.session_token.get()
97    );
98    println!("      Flags: 0b{:08b}", read_login.flags);
99
100    println!(
101        "\n   Data matches: {}\n",
102        read_header == header && read_login == login
103    );
104
105    // Example 3: Building a packet with multiple messages
106    println!("3. Building a multi-message packet:");
107
108    let mut packet = Cursor::new(Vec::new());
109
110    // Write three different messages
111    let headers = [
112        MessageHeader {
113            magic: *b"MSG1",
114            version: 1,
115            message_type: 0x10,
116            payload_length: BigEndian::new(16),
117            sequence_number: LittleEndian::new(100),
118        },
119        MessageHeader {
120            magic: *b"MSG2",
121            version: 1,
122            message_type: 0x20,
123            payload_length: BigEndian::new(16),
124            sequence_number: LittleEndian::new(101),
125        },
126        MessageHeader {
127            magic: *b"MSG3",
128            version: 1,
129            message_type: 0x30,
130            payload_length: BigEndian::new(16),
131            sequence_number: LittleEndian::new(102),
132        },
133    ];
134
135    for header in &headers {
136        packet.write_one(*header)?;
137    }
138
139    let packet_bytes = packet.into_inner();
140    println!("   Packet size: {} bytes", packet_bytes.len());
141    println!(
142        "   Messages per packet: {}",
143        packet_bytes.len() / std::mem::size_of::<MessageHeader>()
144    );
145
146    // Read them back
147    let mut reader = Cursor::new(packet_bytes);
148    println!("\n   Reading messages:");
149    for i in 0..3 {
150        let msg: MessageHeader = reader.read_one()?;
151        println!(
152            "      Message {}: {} (type: 0x{:02X}, seq: {})",
153            i + 1,
154            std::str::from_utf8(&msg.magic).unwrap_or("???"),
155            msg.message_type,
156            msg.sequence_number.get()
157        );
158    }
159
160    // Example 4: Working with status responses
161    println!("\n4. Status response example:");
162
163    let status = StatusResponse {
164        status_code: BigEndian::new(200),
165        timestamp: LittleEndian::new(1700000000),
166        reserved: [0; 6],
167    };
168
169    let mut status_buffer = Cursor::new(Vec::new());
170    status_buffer.write_one(status)?;
171
172    let status_bytes = status_buffer.into_inner();
173    println!("   Status response bytes: {:?}", status_bytes);
174
175    let mut status_reader = Cursor::new(status_bytes);
176    let read_status: StatusResponse = status_reader.read_one()?;
177
178    println!("   Status Code: {}", read_status.status_code.get());
179    println!("   Timestamp: {}", read_status.timestamp.get());
180    println!("   Matches original: {}", read_status == status);
181
182    println!("\n=== Example completed successfully! ===");
183    Ok(())
184}