rocketmq_common/common/message/
message_decoder.rs1use std::collections::HashMap;
16use std::io::Cursor;
17use std::io::Write;
18use std::net::IpAddr;
19use std::net::Ipv4Addr;
20use std::net::Ipv6Addr;
21use std::net::SocketAddr;
22use std::net::SocketAddrV4;
23use std::net::SocketAddrV6;
24use std::str;
25
26use byteorder::BigEndian;
27use byteorder::ByteOrder;
28use bytes::Buf;
29use bytes::BufMut;
30use bytes::Bytes;
31use bytes::BytesMut;
32use cheetah_string::CheetahString;
33
34use crate::common::compression::compressor_factory::CompressorFactory;
35use crate::common::message::message_client_ext::MessageClientExt;
36use crate::common::message::message_ext::MessageExt;
37use crate::common::message::message_id::MessageId;
38use crate::common::message::message_property::MessageProperties;
39use crate::common::message::message_single::Message;
40use crate::common::message::MessageConst;
41use crate::common::message::MessageTrait;
42use crate::common::message::MessageVersion;
43use crate::common::sys_flag::message_sys_flag::MessageSysFlag;
44use crate::utils::util_all;
45use crate::CRC32Utils::crc32;
46use crate::MessageAccessor::MessageAccessor;
47use crate::MessageUtils::build_message_id;
48
49pub const CHARSET_UTF8: &str = "UTF-8";
50pub const MESSAGE_MAGIC_CODE_POSITION: usize = 4;
51pub const MESSAGE_FLAG_POSITION: usize = 16;
52pub const MESSAGE_PHYSIC_OFFSET_POSITION: usize = 28;
53pub const MESSAGE_STORE_TIMESTAMP_POSITION: usize = 56;
54pub const MESSAGE_MAGIC_CODE: i32 = -626843481;
55pub const MESSAGE_MAGIC_CODE_V2: i32 = -626843477;
56pub const BLANK_MAGIC_CODE: i32 = -875286124;
57pub const NAME_VALUE_SEPARATOR: char = '\u{0001}';
58pub const PROPERTY_SEPARATOR: char = '\u{0002}';
59pub const PHY_POS_POSITION: usize = 4 + 4 + 4 + 4 + 4 + 8;
60pub const QUEUE_OFFSET_POSITION: usize = 4 + 4 + 4 + 4 + 4;
61pub const SYSFLAG_POSITION: usize = 4 + 4 + 4 + 4 + 4 + 8 + 8;
62pub const BORN_TIMESTAMP_POSITION: usize = 4 + 4 + 4 + 4 + 4 + 8 + 8 + 4 + 8;
63
64fn get_i16_checked(buffer: &mut Bytes) -> Option<i16> {
65 if buffer.remaining() < 2 {
66 None
67 } else {
68 Some(buffer.get_i16())
69 }
70}
71
72fn get_u8_checked(buffer: &mut Bytes) -> Option<u8> {
73 if buffer.remaining() < 1 {
74 None
75 } else {
76 Some(buffer.get_u8())
77 }
78}
79
80fn get_i32_checked(buffer: &mut Bytes) -> Option<i32> {
81 if buffer.remaining() < 4 {
82 None
83 } else {
84 Some(buffer.get_i32())
85 }
86}
87
88fn get_u32_checked(buffer: &mut Bytes) -> Option<u32> {
89 if buffer.remaining() < 4 {
90 None
91 } else {
92 Some(buffer.get_u32())
93 }
94}
95
96fn get_i64_checked(buffer: &mut Bytes) -> Option<i64> {
97 if buffer.remaining() < 8 {
98 None
99 } else {
100 Some(buffer.get_i64())
101 }
102}
103
104fn split_to_checked(buffer: &mut Bytes, len: usize) -> Option<Bytes> {
105 if buffer.remaining() < len {
106 None
107 } else {
108 Some(buffer.split_to(len))
109 }
110}
111
112fn copy_to_array_checked<const N: usize>(buffer: &mut Bytes) -> Option<[u8; N]> {
113 if buffer.remaining() < N {
114 None
115 } else {
116 let mut bytes = [0; N];
117 buffer.copy_to_slice(&mut bytes);
118 Some(bytes)
119 }
120}
121
122fn get_topic_length_checked(version: MessageVersion, buffer: &mut Bytes) -> Option<usize> {
123 match version {
124 MessageVersion::V1 => get_u8_checked(buffer).map(usize::from),
125 MessageVersion::V2 => {
126 get_i16_checked(buffer).and_then(|value| if value < 0 { None } else { Some(value as usize) })
127 }
128 }
129}
130
131pub fn string_to_message_properties(properties: Option<&CheetahString>) -> HashMap<CheetahString, CheetahString> {
132 let mut map = HashMap::new();
133 if let Some(properties) = properties {
134 let mut index = 0;
135 let len = properties.len();
136 while index < len {
137 let new_index = properties[index..].find(PROPERTY_SEPARATOR).map_or(len, |i| index + i);
138 if new_index - index >= 3 {
139 if let Some(kv_sep_index) = properties[index..new_index].find(NAME_VALUE_SEPARATOR) {
140 let kv_sep_index = index + kv_sep_index;
141 if kv_sep_index > index && kv_sep_index < new_index - 1 {
142 let k = &properties[index..kv_sep_index];
143 let v = &properties[kv_sep_index + 1..new_index];
144 map.insert(CheetahString::from_slice(k), CheetahString::from_slice(v));
145 }
146 }
147 }
148 index = new_index + 1;
149 }
150 }
151 map
152}
153
154pub fn str_to_message_properties(properties: Option<&str>) -> HashMap<CheetahString, CheetahString> {
155 let mut map = HashMap::new();
156 if let Some(properties) = properties {
157 let mut index = 0;
158 let len = properties.len();
159 while index < len {
160 let new_index = properties[index..].find(PROPERTY_SEPARATOR).map_or(len, |i| index + i);
161 if new_index - index >= 3 {
162 if let Some(kv_sep_index) = properties[index..new_index].find(NAME_VALUE_SEPARATOR) {
163 let kv_sep_index = index + kv_sep_index;
164 if kv_sep_index > index && kv_sep_index < new_index - 1 {
165 let k = &properties[index..kv_sep_index];
166 let v = &properties[kv_sep_index + 1..new_index];
167 map.insert(CheetahString::from_slice(k), CheetahString::from_slice(v));
168 }
169 }
170 }
171 index = new_index + 1;
172 }
173 }
174 map
175}
176
177pub fn message_properties_to_string(properties: &HashMap<CheetahString, CheetahString>) -> CheetahString {
178 let mut len = 0;
179 for (name, value) in properties.iter() {
180 len += name.len();
181
182 len += value.len();
183 len += 2; }
185
186 let mut sb = String::with_capacity(len);
187 for (name, value) in properties.iter() {
188 sb.push_str(name);
189 sb.push(NAME_VALUE_SEPARATOR);
190
191 sb.push_str(value);
192 sb.push(PROPERTY_SEPARATOR);
193 }
194 CheetahString::from_string(sb)
195}
196
197pub fn decode_client(
198 byte_buffer: &mut Bytes,
199 read_body: bool,
200 de_compress_body: bool,
201 is_set_properties_string: bool,
202 check_crc: bool,
203) -> Option<MessageClientExt> {
204 decode(
219 byte_buffer,
220 read_body,
221 de_compress_body,
222 false,
223 is_set_properties_string,
224 check_crc,
225 )
226 .map(|msg_ext| MessageClientExt {
227 message_ext_inner: msg_ext,
228 })
229}
230
231pub fn decode(
233 byte_buffer: &mut Bytes,
234 read_body: bool,
235 de_compress_body: bool,
236 is_client: bool,
237 is_set_properties_string: bool,
238 check_crc: bool,
239) -> Option<MessageExt> {
240 let initial_remaining = byte_buffer.remaining();
241 let mut msg_ext = MessageExt::default();
242
243 let store_size = get_i32_checked(byte_buffer)?;
245 if store_size <= 0 || store_size as usize > initial_remaining {
246 return None;
247 }
248 msg_ext.set_store_size(store_size);
249
250 let magic_code = get_i32_checked(byte_buffer)?;
252 let version = MessageVersion::value_of_magic_code(magic_code).ok()?;
253
254 let body_crc = get_u32_checked(byte_buffer)?;
256 msg_ext.set_body_crc(body_crc);
257
258 let queue_id = get_i32_checked(byte_buffer)?;
260 msg_ext.set_queue_id(queue_id);
261
262 let flag = get_i32_checked(byte_buffer)?;
264 msg_ext.message.set_flag(flag);
265
266 let queue_offset = get_i64_checked(byte_buffer)?;
268 msg_ext.set_queue_offset(queue_offset);
269
270 let physic_offset = get_i64_checked(byte_buffer)?;
272 msg_ext.set_commit_log_offset(physic_offset);
273
274 let sys_flag = get_i32_checked(byte_buffer)?;
276 msg_ext.set_sys_flag(sys_flag);
277
278 let born_time_stamp = get_i64_checked(byte_buffer)?;
280 msg_ext.set_born_timestamp(born_time_stamp);
281
282 let (born_host_address, born_host_ip_length) = if sys_flag & MessageSysFlag::BORNHOST_V6_FLAG != 0 {
284 let born_host = copy_to_array_checked::<16>(byte_buffer)?;
285 let port = get_i32_checked(byte_buffer)?;
286 (
287 SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from(born_host), port as u16, 0, 0)),
288 16,
289 )
290 } else {
291 let born_host = copy_to_array_checked::<4>(byte_buffer)?;
292 let port = get_i32_checked(byte_buffer)?;
293 (
294 SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from(born_host), port as u16)),
295 4,
296 )
297 };
298 msg_ext.set_born_host(born_host_address);
299
300 let store_timestamp = get_i64_checked(byte_buffer)?;
302 msg_ext.set_store_timestamp(store_timestamp);
303
304 let (store_host_address, store_host_ip_length) = if sys_flag & MessageSysFlag::STOREHOSTADDRESS_V6_FLAG != 0 {
306 let store_host = copy_to_array_checked::<16>(byte_buffer)?;
307 let port = get_i32_checked(byte_buffer)?;
308 (
309 SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from(store_host), port as u16, 0, 0)),
310 16,
311 )
312 } else {
313 let store_host = copy_to_array_checked::<4>(byte_buffer)?;
314 let port = get_i32_checked(byte_buffer)?;
315 (
316 SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from(store_host), port as u16)),
317 4,
318 )
319 };
320 msg_ext.set_store_host(store_host_address);
321
322 let reconsume_times = get_i32_checked(byte_buffer)?;
324 msg_ext.set_reconsume_times(reconsume_times);
325
326 let prepared_transaction_offset = get_i64_checked(byte_buffer)?;
328 msg_ext.set_prepared_transaction_offset(prepared_transaction_offset);
329
330 let body_len = get_i32_checked(byte_buffer)?;
332 if body_len < 0 {
333 return None;
334 }
335 let body_len = body_len as usize;
336 if body_len > 0 {
337 if read_body {
339 let body = split_to_checked(byte_buffer, body_len)?;
340 if check_crc {
341 let crc = crc32(&body);
342 if crc != body_crc {
343 return None;
344 }
345 }
346 let mut body_bytes = body;
347 if de_compress_body && (sys_flag & MessageSysFlag::COMPRESSED_FLAG) == MessageSysFlag::COMPRESSED_FLAG {
348 let compression_type = MessageSysFlag::try_get_compression_type(sys_flag).ok()?;
349 body_bytes = compression_type.try_decompression(&body_bytes).ok()?;
350 }
351 msg_ext.message.set_body(Some(body_bytes));
352 } else {
353 let _ = split_to_checked(byte_buffer, body_len)?;
354 }
355 }
356
357 let _address_len = born_host_ip_length + store_host_ip_length;
359 let topic_len = get_topic_length_checked(version, byte_buffer)?;
360 let topic = split_to_checked(byte_buffer, topic_len)?;
361 let topic_str = str::from_utf8(&topic).ok()?;
362 msg_ext.message.set_topic(CheetahString::from_slice(topic_str));
363
364 let properties_length = get_i16_checked(byte_buffer)?;
366 if properties_length < 0 {
367 return None;
368 }
369 if properties_length > 0 {
370 let properties = split_to_checked(byte_buffer, properties_length as usize)?;
372 if !is_set_properties_string {
373 let properties_string =
375 CheetahString::from_string(String::from_utf8_lossy(properties.as_ref()).to_string());
376 let message_properties = string_to_message_properties(Some(&properties_string));
377 *msg_ext.message.properties_mut() = MessageProperties::from_map(message_properties);
378 } else {
379 let properties_string =
380 CheetahString::from_string(String::from_utf8_lossy(properties.as_ref()).to_string());
381 let mut message_properties = string_to_message_properties(Some(&properties_string));
382 message_properties.insert(CheetahString::from_static_str("propertiesString"), properties_string);
383 *msg_ext.message.properties_mut() = MessageProperties::from_map(message_properties);
384 }
385 }
386 let msg_id = build_message_id(store_host_address, physic_offset);
387 msg_ext.set_msg_id(CheetahString::from_string(msg_id));
388
389 Some(msg_ext)
390}
391
392pub fn count_inner_msg_num(bytes: Option<Bytes>) -> u32 {
393 match bytes {
394 None => 0,
395 Some(mut bytes) => {
396 let mut count = 0;
397 while bytes.has_remaining() {
398 let size = bytes.slice(0..4).get_i32();
399 if size as usize > bytes.len() {
400 break;
401 }
402 let _ = bytes.split_to(size as usize);
403 count += 1;
404 }
405 count
406 }
407 }
408}
409
410pub fn encode_messages(messages: &[Message]) -> Bytes {
411 let mut bytes = BytesMut::new();
412 for message in messages {
414 let message_bytes = encode_message(message);
415 bytes.put_slice(&message_bytes);
417 }
418 bytes.freeze()
419}
420
421pub fn encode_message(message: &Message) -> Bytes {
422 let empty_body = Bytes::new();
423 let body = message.get_body().unwrap_or(&empty_body);
424 let body_len = body.len();
425 let properties = message_properties_to_string(message.properties().as_map());
426 let properties_bytes = properties.as_bytes();
427 let properties_length = properties_bytes.len();
428
429 let store_size = 4 + 4 + 4 + 4 + 4 + body_len + 2 + properties_length;
435
436 let mut bytes = BytesMut::with_capacity(store_size);
437
438 bytes.put_i32(store_size as i32);
440
441 bytes.put_i32(0);
443
444 bytes.put_u32(0);
446
447 bytes.put_i32(message.flag());
449
450 bytes.put_i32(body_len as i32);
452 bytes.put_slice(body);
453
454 bytes.put_i16(properties_length as i16);
456 bytes.put_slice(properties_bytes);
457
458 bytes.freeze()
459}
460
461pub fn decodes_batch(byte_buffer: &mut Bytes, read_body: bool, decompress_body: bool) -> Vec<MessageExt> {
462 let mut messages = Vec::new();
463 while byte_buffer.has_remaining() {
464 if let Some(msg_ext) = decode(byte_buffer, read_body, decompress_body, false, false, false) {
465 messages.push(msg_ext);
466 } else {
467 break;
468 }
469 }
470 messages
471}
472
473pub fn decodes_batch_client(byte_buffer: &mut Bytes, read_body: bool, decompress_body: bool) -> Vec<MessageClientExt> {
474 let mut messages = Vec::new();
475 while byte_buffer.has_remaining() {
476 if let Some(msg_ext) = decode_client(byte_buffer, read_body, decompress_body, false, false) {
477 messages.push(msg_ext);
478 } else {
479 break;
480 }
481 }
482 messages
483}
484
485pub fn decode_messages_from(mut message_ext: MessageExt, vec_: &mut Vec<MessageExt>) {
486 let Some(body) = message_ext.message.body_mut().raw_mut().as_mut() else {
487 return;
488 };
489 let messages = decode_messages(body);
490 for message in messages {
491 let mut message_ext_inner = MessageExt {
492 message,
493 ..MessageExt::default()
494 };
495 message_ext_inner.set_topic(message_ext.topic().to_owned());
496 message_ext_inner.queue_offset = message_ext.queue_offset;
497 message_ext_inner.queue_id = message_ext.queue_id;
498 message_ext_inner.set_flag(message_ext.get_flag());
499 message_ext_inner.store_host = message_ext.store_host;
503 message_ext_inner.born_host = message_ext.born_host;
504 message_ext_inner.store_timestamp = message_ext.store_timestamp;
505 message_ext_inner.born_timestamp = message_ext.born_timestamp;
506 message_ext_inner.sys_flag = message_ext.sys_flag;
507 message_ext_inner.commit_log_offset = message_ext.commit_log_offset;
508 message_ext_inner.set_wait_store_msg_ok(message_ext.is_wait_store_msg_ok());
509 vec_.push(message_ext_inner);
510 }
511}
512
513pub fn decode_messages(buffer: &mut Bytes) -> Vec<Message> {
514 let mut messages = Vec::new();
515 while buffer.has_remaining() {
516 let Some(message) = try_decode_message(buffer) else {
517 break;
518 };
519 messages.push(message);
520 }
521 messages
522}
523
524pub fn decode_message(buffer: &mut Bytes) -> Message {
525 try_decode_message(buffer).unwrap_or_default()
526}
527
528fn try_decode_message(buffer: &mut Bytes) -> Option<Message> {
529 let store_size = get_i32_checked(buffer)?;
531 if store_size <= 0 {
532 return None;
533 }
534
535 let _ = get_i32_checked(buffer)?;
537
538 let _ = get_i32_checked(buffer)?;
540
541 let flag = get_i32_checked(buffer)?;
543
544 let body_len = get_i32_checked(buffer)?;
546 if body_len < 0 {
547 return None;
548 }
549 let body = split_to_checked(buffer, body_len as usize)?;
550
551 let properties_length = get_i16_checked(buffer)?;
553 if properties_length < 0 {
554 return None;
555 }
556 let properties = split_to_checked(buffer, properties_length as usize)?;
557 let message_properties = str_to_message_properties(Some(str::from_utf8(&properties).ok()?));
560
561 let mut message = Message::default();
562 message.set_body(Some(body));
563 message.set_properties(message_properties);
564 message.set_flag(flag);
565 Some(message)
566}
567
568const MSG_ID_IPV4_LEN: usize = 32;
569const MSG_ID_IPV6_LEN: usize = 56;
570
571pub fn validate_message_id(msg_id: &str) -> Result<(), String> {
572 let msg_id = msg_id.trim();
573
574 if msg_id.is_empty() {
575 return Err("Message ID cannot be empty".to_string());
576 }
577
578 let len = msg_id.len();
579 if len != MSG_ID_IPV4_LEN && len != MSG_ID_IPV6_LEN {
580 return Err(format!(
581 "Invalid message ID length: {len}. Expected {MSG_ID_IPV4_LEN} characters (IPv4) or {MSG_ID_IPV6_LEN} \
582 characters (IPv6)"
583 ));
584 }
585
586 if !msg_id.bytes().all(|b| b.is_ascii_hexdigit()) {
587 return Err("Message ID must be a valid hexadecimal string".to_string());
588 }
589
590 Ok(())
591}
592
593pub fn decode_message_id(msg_id: &str) -> Result<MessageId, String> {
594 validate_message_id(msg_id)?;
595 let bytes = util_all::string_to_bytes(msg_id)
596 .ok_or_else(|| "Failed to decode message ID: invalid hex string".to_string())?;
597 let mut buffer = Bytes::from(bytes);
598 let address = if msg_id.len() == 32 {
599 let mut ip = [0u8; 4];
600 buffer.copy_to_slice(&mut ip);
601 let port = buffer.get_i32();
602 SocketAddr::new(IpAddr::V4(Ipv4Addr::from(ip)), port as u16)
603 } else {
604 let mut ip = [0u8; 16];
605 buffer.copy_to_slice(&mut ip);
606 let port = buffer.get_i32();
607 SocketAddr::new(IpAddr::V6(Ipv6Addr::from(ip)), port as u16)
608 };
609 Ok(MessageId {
610 address,
611 offset: buffer.get_i64(),
612 })
613}
614
615pub fn encode(message_ext: &MessageExt, need_compress: bool) -> rocketmq_error::RocketMQResult<Bytes> {
616 let body = message_ext
617 .get_body()
618 .ok_or_else(|| rocketmq_error::RocketMQError::illegal_argument("message body is required"))?;
619 let topic = message_ext.topic().as_bytes();
620 let topic_len = topic.len();
621 let properties = message_properties_to_string(message_ext.get_properties());
622 let properties_bytes = properties.as_bytes();
623 let properties_length = properties_bytes.len();
624 let sys_flag = message_ext.sys_flag;
625 let born_host_length = if (sys_flag & MessageSysFlag::BORNHOST_V6_FLAG) == 0 {
626 8
627 } else {
628 20
629 };
630 let store_host_address_length = if (sys_flag & MessageSysFlag::STOREHOSTADDRESS_V6_FLAG) == 0 {
631 8
632 } else {
633 20
634 };
635 let new_body = if need_compress && (sys_flag & MessageSysFlag::COMPRESSED_FLAG) == MessageSysFlag::COMPRESSED_FLAG {
636 let compressor = CompressorFactory::get_compressor(MessageSysFlag::try_get_compression_type(sys_flag)?);
637 let compressed_body = compressor.compress(body, 5)?;
638 Some(compressed_body)
639 } else {
640 None
641 };
642 let body_len = new_body.as_ref().map_or(body.len(), |b| b.len());
643 let store_size = if message_ext.store_size > 0 {
644 message_ext.store_size as usize
645 } else {
646 4 + 4 + 4 + 4 + 4 + 8 + 8 + 4 + 8 + born_host_length + 8 + store_host_address_length + 4 + 8 + 4 + body_len + 1 + topic_len + 2 + properties_length };
664 let mut byte_buffer = BytesMut::with_capacity(store_size);
665
666 byte_buffer.put_i32(store_size as i32);
668
669 byte_buffer.put_i32(MESSAGE_MAGIC_CODE);
671
672 byte_buffer.put_u32(message_ext.body_crc);
674
675 byte_buffer.put_i32(message_ext.queue_id);
677
678 byte_buffer.put_i32(message_ext.message.flag());
680
681 byte_buffer.put_i64(message_ext.queue_offset);
683
684 byte_buffer.put_i64(message_ext.commit_log_offset);
686
687 byte_buffer.put_i32(message_ext.sys_flag);
689
690 byte_buffer.put_i64(message_ext.born_timestamp);
692
693 let born_host = message_ext.born_host;
696 match born_host {
697 SocketAddr::V4(value) => byte_buffer.extend(value.ip().octets()),
698 SocketAddr::V6(value) => byte_buffer.extend(value.ip().octets()),
699 };
700
701 byte_buffer.put_i32(born_host.port() as i32);
702
703 byte_buffer.put_i64(message_ext.store_timestamp);
705
706 let store_host = message_ext.store_host;
709 match store_host {
710 SocketAddr::V4(value) => byte_buffer.extend(value.ip().octets()),
711 SocketAddr::V6(value) => byte_buffer.extend(value.ip().octets()),
712 };
713
714 byte_buffer.put_i32(store_host.port() as i32);
715
716 byte_buffer.put_i32(message_ext.reconsume_times);
718
719 byte_buffer.put_i64(message_ext.prepared_transaction_offset);
721
722 byte_buffer.put_i32(body_len as i32);
724 if let Some(new_body) = new_body {
725 byte_buffer.put_slice(&new_body);
726 } else {
727 byte_buffer.put_slice(body);
728 }
729
730 byte_buffer.put_u8(topic_len as u8);
732 byte_buffer.put_slice(topic);
733
734 byte_buffer.put_i16(properties_length as i16);
736 byte_buffer.put_slice(properties_bytes);
737
738 Ok(byte_buffer.freeze())
739}
740
741pub fn encode_uniquely(message_ext: &MessageExt, need_compress: bool) -> rocketmq_error::RocketMQResult<Bytes> {
742 let body = message_ext
743 .get_body()
744 .ok_or_else(|| rocketmq_error::RocketMQError::illegal_argument("message body is required"))?;
745 let topics = message_ext.topic().as_bytes();
746 let topic_len = topics.len();
747 let properties = message_properties_to_string(message_ext.get_properties());
748 let properties_bytes = properties.as_bytes();
749 let properties_length = properties_bytes.len();
750 let sys_flag = message_ext.sys_flag;
751 let born_host_length = if (sys_flag & MessageSysFlag::BORNHOST_V6_FLAG) == 0 {
752 8
753 } else {
754 20
755 };
756 let new_body = if need_compress && (sys_flag & MessageSysFlag::COMPRESSED_FLAG) == MessageSysFlag::COMPRESSED_FLAG {
757 let compressor = CompressorFactory::get_compressor(MessageSysFlag::try_get_compression_type(sys_flag)?);
758 let compressed_body = compressor.compress(body, 5)?;
759 Some(compressed_body)
760 } else {
761 None
762 };
763 let body_len = new_body.as_ref().map_or(body.len(), |b| b.len());
764 let store_size = if message_ext.store_size > 0 {
765 message_ext.store_size as usize
766 } else {
767 4 + 4 + 4 + 4 + 4 + 8 + 8 + 4 + 8 + born_host_length + 4 + 8 + 4 + body_len + 1 + topic_len + 2 + properties_length };
783 let capacity = if message_ext.store_size > 0 {
784 store_size.saturating_sub(8)
785 } else {
786 store_size
787 };
788 let mut byte_buffer = BytesMut::with_capacity(capacity);
789
790 byte_buffer.put_i32(store_size as i32);
792
793 byte_buffer.put_i32(MESSAGE_MAGIC_CODE);
795
796 byte_buffer.put_u32(message_ext.body_crc);
798
799 byte_buffer.put_i32(message_ext.queue_id);
801
802 byte_buffer.put_i32(message_ext.message.flag());
804
805 byte_buffer.put_i64(message_ext.queue_offset);
807
808 byte_buffer.put_i64(message_ext.commit_log_offset);
810
811 byte_buffer.put_i32(message_ext.sys_flag);
813
814 byte_buffer.put_i64(message_ext.born_timestamp);
816
817 let born_host = message_ext.born_host;
820 match born_host {
821 SocketAddr::V4(value) => byte_buffer.extend(value.ip().octets()),
822 SocketAddr::V6(value) => byte_buffer.extend(value.ip().octets()),
823 };
824 byte_buffer.put_i32(born_host.port() as i32);
825
826 byte_buffer.put_i32(message_ext.reconsume_times);
828
829 byte_buffer.put_i64(message_ext.prepared_transaction_offset);
831
832 byte_buffer.put_i32(body_len as i32);
834 if let Some(new_body) = new_body {
835 byte_buffer.put_slice(&new_body);
836 } else {
837 byte_buffer.put_slice(body);
838 }
839
840 byte_buffer.put_i16(topic_len as i16);
842 byte_buffer.put_slice(topics);
843
844 byte_buffer.put_i16(properties_length as i16);
846 byte_buffer.put_slice(properties_bytes);
847
848 Ok(byte_buffer.freeze())
849}
850
851pub fn create_crc32(mut input: &mut [u8], crc32: u32) {
852 input.put(MessageConst::PROPERTY_CRC32.as_bytes());
853 input.put_u8(NAME_VALUE_SEPARATOR as u8);
854 let mut crc32 = crc32;
855 for _ in 0..10 {
856 let mut b = b'0';
857 if crc32 > 0 {
858 b += (crc32 % 10) as u8;
859 crc32 /= 10;
860 }
861 input.put_u8(b);
862 }
863 input.put_u8(PROPERTY_SEPARATOR as u8);
864}
865
866pub fn decode_properties(bytes: &mut Bytes) -> Option<HashMap<CheetahString, CheetahString>> {
867 if bytes.len() < SYSFLAG_POSITION + 4 {
869 return None;
870 }
871
872 let sys_flag = BigEndian::read_i32(&bytes[SYSFLAG_POSITION..SYSFLAG_POSITION + 4]);
874 let magic_code = BigEndian::read_i32(&bytes[MESSAGE_MAGIC_CODE_POSITION..MESSAGE_MAGIC_CODE_POSITION + 4]);
875 let version = match MessageVersion::value_of_magic_code(magic_code) {
876 Ok(value) => value,
877 Err(_) => return None,
878 };
879
880 let bornhost_length = if (sys_flag & MessageSysFlag::BORNHOST_V6_FLAG) == 0 {
882 8
883 } else {
884 20
885 };
886 let storehost_address_length = if (sys_flag & MessageSysFlag::STOREHOSTADDRESS_V6_FLAG) == 0 {
887 8
888 } else {
889 20
890 };
891
892 let body_size_position = 4 + 4 + 4 + 4 + 4 + 8 + 8 + 4 + 8 + bornhost_length + 8 + storehost_address_length + 4 + 8; if bytes.len() < body_size_position + 4 {
909 return None;
910 }
911
912 let body_size = BigEndian::read_i32(&bytes[body_size_position..body_size_position + 4]) as usize;
914
915 let topic_length_position = body_size_position + 4 + body_size;
917 if bytes.len() < topic_length_position {
918 return None;
919 }
920
921 let slice = &bytes[topic_length_position..];
923 let cursor = Cursor::new(slice);
924 let topic_length_size = version.get_topic_length_size();
925 bytes.advance(topic_length_position);
926 let topic_length = version.get_topic_length(bytes);
927
928 let properties_position = topic_length_position + topic_length_size + topic_length;
930 if bytes.len() < properties_position + 2 {
931 return None;
932 }
933
934 let properties_length = BigEndian::read_i16(&bytes[properties_position..properties_position + 2]);
936
937 let properties_start = properties_position + 2;
939 if properties_length > 0 {
940 let end = properties_start + (properties_length as usize);
941 if bytes.len() < end {
942 return None;
943 }
944 let properties_bytes = &bytes[properties_start..end];
945 if let Ok(properties_string) = String::from_utf8(properties_bytes.to_vec()) {
946 Some(string_to_message_properties(Some(&CheetahString::from_string(
947 properties_string,
948 ))))
949 } else {
950 None
951 }
952 } else {
953 None
954 }
955}
956
957#[cfg(test)]
958mod tests {
959 use bytes::BufMut;
960 use bytes::BytesMut;
961
962 use super::*;
963
964 #[test]
965 fn count_inner_msg_num_counts_correctly_for_multiple_messages() {
966 let mut bytes = BytesMut::new();
967 bytes.put_i32(8);
968 bytes.put_slice(&[0, 0, 0, 0]);
969 bytes.put_i32(8);
970 bytes.put_slice(&[0, 0, 0, 0]);
971 assert_eq!(count_inner_msg_num(Some(bytes.freeze())), 2);
972 }
973
974 #[test]
975 fn count_inner_msg_num_counts_correctly_for_single_message() {
976 let mut bytes = BytesMut::new();
977 bytes.put_i32(8);
978 bytes.put_slice(&[0, 0, 0, 0]);
979 assert_eq!(count_inner_msg_num(Some(bytes.freeze())), 1);
980 }
981
982 #[test]
983 fn count_inner_msg_num_counts_zero_for_no_messages() {
984 let bytes = BytesMut::new();
985 assert_eq!(count_inner_msg_num(Some(bytes.freeze())), 0);
986 }
987
988 #[test]
989 fn count_inner_msg_num_ignores_incomplete_messages() {
990 let mut bytes = BytesMut::new();
991 bytes.put_i32(4);
992 assert_eq!(count_inner_msg_num(Some(bytes.freeze())), 1);
993 }
994
995 #[test]
996 fn decode_message_id_ipv4() {
997 let msg_id = "7F0000010007D8260BF075769D36C348";
998 let message_id = decode_message_id(msg_id).unwrap();
999 assert_eq!(message_id.address, "127.0.0.1:55334".parse().unwrap());
1000 assert_eq!(message_id.offset, 860316681131967304);
1001 }
1002
1003 #[test]
1004 fn encode_with_compression() {
1005 let mut message_ext = MessageExt::default();
1006 message_ext.set_body(Bytes::from("Hello, World!"));
1007 let result = encode(&message_ext, true);
1008 assert!(result.is_ok());
1009 let bytes = result.unwrap();
1010 assert!(!bytes.is_empty());
1011 }
1012
1013 #[test]
1014 fn encode_with_unknown_compression_type_returns_error() {
1015 let mut message_ext = MessageExt::default();
1016 message_ext.set_body(Bytes::from_static(b"Hello, World!"));
1017 message_ext.set_sys_flag(MessageSysFlag::COMPRESSED_FLAG | (0x7 << 8));
1018
1019 let result = encode(&message_ext, true);
1020
1021 assert!(result.is_err());
1022 }
1023
1024 #[test]
1025 fn decode_compressed_body_uses_sys_flag_compression_type() {
1026 let body = Bytes::from_static(b"Hello from compressed RocketMQ body");
1027
1028 for compression_flag in [
1029 MessageSysFlag::COMPRESSION_LZ4_TYPE,
1030 MessageSysFlag::COMPRESSION_ZSTD_TYPE,
1031 MessageSysFlag::COMPRESSION_ZLIB_TYPE,
1032 ] {
1033 let mut message_ext = MessageExt::default();
1034 message_ext.set_body(body.clone());
1035 message_ext.set_sys_flag(MessageSysFlag::COMPRESSED_FLAG | compression_flag);
1036 let mut encoded = encode(&message_ext, true).expect("compressed message should encode");
1037
1038 let decoded =
1039 decode(&mut encoded, true, true, false, false, false).expect("compressed message should decode");
1040
1041 assert_eq!(decoded.get_body(), Some(&body));
1042 }
1043 }
1044
1045 #[test]
1046 fn encode_without_compression() {
1047 let mut message_ext = MessageExt::default();
1048 message_ext.set_body(Bytes::from("Hello, World!"));
1049 let result = encode(&message_ext, false);
1050 assert!(result.is_ok());
1051 let bytes = result.unwrap();
1052 assert!(!bytes.is_empty());
1053 }
1054
1055 #[test]
1056 fn encode_with_empty_body() {
1057 let mut message_ext = MessageExt::default();
1058 message_ext.set_body(Bytes::new());
1059 let result = encode(&message_ext, false);
1060 assert!(result.is_ok());
1061 let bytes = result.unwrap();
1062 assert!(!bytes.is_empty());
1063 }
1064
1065 #[test]
1066 fn encode_with_large_body() {
1067 let mut message_ext = MessageExt::default();
1068 let large_body = vec![0u8; 1024 * 1024];
1069 message_ext.set_body(Bytes::from(large_body));
1070 let result = encode(&message_ext, false);
1071 assert!(result.is_ok());
1072 let bytes = result.unwrap();
1073 assert!(!bytes.is_empty());
1074 }
1075
1076 #[test]
1077 fn encode_uniquely_with_compression() {
1078 let mut message_ext = MessageExt::default();
1079 message_ext.set_body(Bytes::from("Hello, World!"));
1080 let result = encode_uniquely(&message_ext, true);
1081 assert!(result.is_ok());
1082 let bytes = result.unwrap();
1083 assert!(!bytes.is_empty());
1084 }
1085
1086 #[test]
1087 fn encode_uniquely_without_compression() {
1088 let mut message_ext = MessageExt::default();
1089 message_ext.set_body(Bytes::from("Hello, World!"));
1090 let result = encode_uniquely(&message_ext, false);
1091 assert!(result.is_ok());
1092 let bytes = result.unwrap();
1093 assert!(!bytes.is_empty());
1094 }
1095
1096 #[test]
1097 fn encode_uniquely_with_empty_body() {
1098 let mut message_ext = MessageExt::default();
1099 message_ext.set_body(Bytes::new());
1100 let result = encode_uniquely(&message_ext, false);
1101 assert!(result.is_ok());
1102 let bytes = result.unwrap();
1103 assert!(!bytes.is_empty());
1104 }
1105
1106 #[test]
1107 fn encode_uniquely_with_large_body() {
1108 let mut message_ext = MessageExt::default();
1109 let large_body = vec![0u8; 1024 * 1024];
1110 message_ext.set_body(Bytes::from(large_body));
1111 let result = encode_uniquely(&message_ext, false);
1112 assert!(result.is_ok());
1113 let bytes = result.unwrap();
1114 assert!(!bytes.is_empty());
1115 }
1116
1117 #[test]
1118 fn decode_properties_returns_none_if_bytes_length_is_insufficient() {
1119 let mut bytes = Bytes::from(vec![0; SYSFLAG_POSITION + 3]);
1120 assert!(decode_properties(&mut bytes).is_none());
1121 }
1122
1123 #[test]
1124 fn decode_properties_returns_none_if_magic_code_is_invalid() {
1125 let mut bytes = BytesMut::from_iter(vec![0u8; SYSFLAG_POSITION + 4 + MESSAGE_MAGIC_CODE_POSITION + 4]);
1126 BigEndian::write_i32(&mut bytes[SYSFLAG_POSITION..SYSFLAG_POSITION + 4], 0);
1127 BigEndian::write_i32(
1128 &mut bytes[MESSAGE_MAGIC_CODE_POSITION..MESSAGE_MAGIC_CODE_POSITION + 4],
1129 -1,
1130 );
1131 assert!(decode_properties(&mut bytes.freeze()).is_none());
1132 }
1133
1134 #[test]
1135 fn decode_properties_returns_none_if_body_size_is_insufficient() {
1136 let mut bytes = BytesMut::from_iter(vec![0u8; SYSFLAG_POSITION + 4 + MESSAGE_MAGIC_CODE_POSITION + 4 + 4]);
1137 BigEndian::write_i32(&mut bytes[SYSFLAG_POSITION..SYSFLAG_POSITION + 4], 0);
1138 BigEndian::write_i32(
1139 &mut bytes[MESSAGE_MAGIC_CODE_POSITION..MESSAGE_MAGIC_CODE_POSITION + 4],
1140 MESSAGE_MAGIC_CODE,
1141 );
1142 assert!(decode_properties(&mut bytes.freeze()).is_none());
1143 }
1144
1145 #[test]
1146 fn decode_properties_returns_none_if_topic_length_is_insufficient() {
1147 let mut bytes = BytesMut::from_iter(vec![
1148 0u8;
1149 SYSFLAG_POSITION + 4 + MESSAGE_MAGIC_CODE_POSITION + 4 + 4 + 4
1150 ]);
1151 BigEndian::write_i32(&mut bytes[SYSFLAG_POSITION..SYSFLAG_POSITION + 4], 0);
1152 BigEndian::write_i32(
1153 &mut bytes[MESSAGE_MAGIC_CODE_POSITION..MESSAGE_MAGIC_CODE_POSITION + 4],
1154 MESSAGE_MAGIC_CODE,
1155 );
1156 BigEndian::write_i32(
1157 &mut bytes[SYSFLAG_POSITION + 4 + MESSAGE_MAGIC_CODE_POSITION + 4
1158 ..SYSFLAG_POSITION + 4 + MESSAGE_MAGIC_CODE_POSITION + 4 + 4],
1159 0,
1160 );
1161 assert!(decode_properties(&mut bytes.freeze()).is_none());
1162 }
1163
1164 #[test]
1165 fn decode_properties_returns_none_if_properties_length_is_insufficient() {
1166 let mut bytes = BytesMut::from_iter(vec![
1167 0u8;
1168 SYSFLAG_POSITION + 4 + MESSAGE_MAGIC_CODE_POSITION + 4 + 4 + 4 + 2
1169 ]);
1170 BigEndian::write_i32(&mut bytes[SYSFLAG_POSITION..SYSFLAG_POSITION + 4], 0);
1171 BigEndian::write_i32(
1172 &mut bytes[MESSAGE_MAGIC_CODE_POSITION..MESSAGE_MAGIC_CODE_POSITION + 4],
1173 MESSAGE_MAGIC_CODE,
1174 );
1175 BigEndian::write_i32(
1176 &mut bytes[SYSFLAG_POSITION + 4 + MESSAGE_MAGIC_CODE_POSITION + 4
1177 ..SYSFLAG_POSITION + 4 + MESSAGE_MAGIC_CODE_POSITION + 4 + 4],
1178 0,
1179 );
1180 BigEndian::write_i16(
1181 &mut bytes[SYSFLAG_POSITION + 4 + MESSAGE_MAGIC_CODE_POSITION + 4 + 4 + 4
1182 ..SYSFLAG_POSITION + 4 + MESSAGE_MAGIC_CODE_POSITION + 4 + 4 + 4 + 2],
1183 1,
1184 );
1185 assert!(decode_properties(&mut bytes.freeze()).is_none());
1186 }
1187
1188 #[test]
1189 fn validate_message_id_ipv4_32_chars() {
1190 let result = validate_message_id("AC11000100002A9F0000000000000001");
1191 assert!(result.is_ok());
1192 }
1193
1194 #[test]
1195 fn validate_message_id_ipv6_56_chars() {
1196 let result = validate_message_id("20010db800000000000000000000000100002A9F0000000000000001");
1197 assert!(result.is_ok());
1198 }
1199
1200 #[test]
1201 fn validate_message_id_ipv6_40_chars_rejected() {
1202 let result = validate_message_id("20010db800000000000000000000000100000001");
1203 assert!(result.is_err());
1204 if let Err(e) = result {
1205 assert!(e.contains("Invalid message ID length"));
1206 assert!(e.contains("56 characters (IPv6)"));
1207 }
1208 }
1209
1210 #[test]
1211 fn decode_message_id_ipv6() {
1212 let msg_id = "20010db800000000000000000000000100002A9F0000000000000001";
1213 let message_id = decode_message_id(msg_id).unwrap();
1214 assert_eq!(message_id.address, "[2001:db8::1]:10911".parse().unwrap());
1215 assert_eq!(message_id.offset, 1);
1216 }
1217
1218 #[test]
1219 fn decode_message_id_ipv6_full_address() {
1220 let msg_id = "20010db81234567800000000abcdef0100002A9F0000000000001234";
1221 let message_id = decode_message_id(msg_id).unwrap();
1222 assert_eq!(
1223 message_id.address,
1224 "[2001:db8:1234:5678::abcd:ef01]:10911".parse().unwrap()
1225 );
1226 assert_eq!(message_id.offset, 4660);
1227 }
1228}