@@ -94,11 +94,17 @@ impl IggyMessageHeader {
9494 . try_into ( )
9595 . map_err ( |_| IggyError :: InvalidNumberEncoding ) ?,
9696 ) ,
97- reserved : u64:: from_le_bytes (
98- bytes[ IGGY_MESSAGE_RESERVED_OFFSET_RANGE ]
99- . try_into ( )
100- . map_err ( |_| IggyError :: InvalidNumberEncoding ) ?,
101- ) ,
97+ reserved : {
98+ let reserved = u64:: from_le_bytes (
99+ bytes[ IGGY_MESSAGE_RESERVED_OFFSET_RANGE ]
100+ . try_into ( )
101+ . map_err ( |_| IggyError :: InvalidNumberEncoding ) ?,
102+ ) ;
103+ if reserved != 0 {
104+ return Err ( IggyError :: InvalidReservedField ( reserved) ) ;
105+ }
106+ reserved
107+ } ,
102108 } )
103109 }
104110}
@@ -164,12 +170,16 @@ impl BytesSerializable for IggyMessageHeader {
164170 . map_err ( |_| IggyError :: InvalidNumberEncoding ) ?,
165171 ) ;
166172
167- let _reserved = u64:: from_le_bytes (
173+ let reserved = u64:: from_le_bytes (
168174 bytes[ IGGY_MESSAGE_RESERVED_OFFSET_RANGE ]
169175 . try_into ( )
170176 . map_err ( |_| IggyError :: InvalidNumberEncoding ) ?,
171177 ) ;
172178
179+ if reserved != 0 {
180+ return Err ( IggyError :: InvalidReservedField ( reserved) ) ;
181+ }
182+
173183 Ok ( IggyMessageHeader {
174184 checksum,
175185 id,
@@ -178,7 +188,7 @@ impl BytesSerializable for IggyMessageHeader {
178188 origin_timestamp,
179189 user_headers_length : headers_length,
180190 payload_length,
181- reserved : _reserved ,
191+ reserved,
182192 } )
183193 }
184194}
@@ -245,4 +255,60 @@ mod tests {
245255 assert_eq ! ( header. user_headers_length, deserialized. user_headers_length) ;
246256 assert_eq ! ( header. payload_length, deserialized. payload_length) ;
247257 }
258+
259+ #[ test]
260+ fn should_reject_non_zero_reserved_field_from_bytes ( ) {
261+ let header = IggyMessageHeader {
262+ checksum : 123456789 ,
263+ id : 987654321 ,
264+ offset : 100 ,
265+ timestamp : 1000000 ,
266+ origin_timestamp : 999999 ,
267+ user_headers_length : 50 ,
268+ payload_length : 200 ,
269+ reserved : 0 ,
270+ } ;
271+
272+ // First serialize with reserved = 0
273+ let mut bytes = header. to_bytes ( ) . to_vec ( ) ;
274+
275+ // Manually set reserved field to non-zero value (last 8 bytes)
276+ let non_zero_reserved: u64 = 42 ;
277+ bytes[ IGGY_MESSAGE_RESERVED_OFFSET_RANGE ] . copy_from_slice ( & non_zero_reserved. to_le_bytes ( ) ) ;
278+
279+ let result = IggyMessageHeader :: from_bytes ( Bytes :: from ( bytes) ) ;
280+ assert ! ( result. is_err( ) ) ;
281+ assert_eq ! (
282+ result. unwrap_err( ) ,
283+ IggyError :: InvalidReservedField ( non_zero_reserved)
284+ ) ;
285+ }
286+
287+ #[ test]
288+ fn should_reject_non_zero_reserved_field_from_raw_bytes ( ) {
289+ let header = IggyMessageHeader {
290+ checksum : 111 ,
291+ id : 222 ,
292+ offset : 333 ,
293+ timestamp : 444 ,
294+ origin_timestamp : 555 ,
295+ user_headers_length : 66 ,
296+ payload_length : 77 ,
297+ reserved : 0 ,
298+ } ;
299+
300+ // First serialize with reserved = 0
301+ let mut bytes = header. to_bytes ( ) . to_vec ( ) ;
302+
303+ // Manually set reserved field to non-zero value
304+ let non_zero_reserved: u64 = 123456789 ;
305+ bytes[ IGGY_MESSAGE_RESERVED_OFFSET_RANGE ] . copy_from_slice ( & non_zero_reserved. to_le_bytes ( ) ) ;
306+
307+ let result = IggyMessageHeader :: from_raw_bytes ( & bytes) ;
308+ assert ! ( result. is_err( ) ) ;
309+ assert_eq ! (
310+ result. unwrap_err( ) ,
311+ IggyError :: InvalidReservedField ( non_zero_reserved)
312+ ) ;
313+ }
248314}
0 commit comments