Skip to main content

rocketmq_common/common/message/
message_decoder.rs

1// Copyright 2023 The RocketMQ Rust Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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; // separator
184    }
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    /*if let Some(msg_ext) = decode(
205        byte_buffer,
206        read_body,
207        de_compress_body,
208        false,
209        is_set_properties_string,
210        check_crc,
211    ) {
212        Some(MessageClientExt {
213            message_ext_inner: msg_ext,
214        })
215    } else {
216        None
217    }*/
218    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
231//this method will optimize later
232pub 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    // 1 TOTALSIZE
244    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    // 2 MAGICCODE
251    let magic_code = get_i32_checked(byte_buffer)?;
252    let version = MessageVersion::value_of_magic_code(magic_code).ok()?;
253
254    // 3 BODYCRC
255    let body_crc = get_u32_checked(byte_buffer)?;
256    msg_ext.set_body_crc(body_crc);
257
258    // 4 QUEUEID
259    let queue_id = get_i32_checked(byte_buffer)?;
260    msg_ext.set_queue_id(queue_id);
261
262    // 5 FLAG
263    let flag = get_i32_checked(byte_buffer)?;
264    msg_ext.message.set_flag(flag);
265
266    // 6 QUEUEOFFSET
267    let queue_offset = get_i64_checked(byte_buffer)?;
268    msg_ext.set_queue_offset(queue_offset);
269
270    // 7 PHYSICALOFFSET
271    let physic_offset = get_i64_checked(byte_buffer)?;
272    msg_ext.set_commit_log_offset(physic_offset);
273
274    // 8 SYSFLAG
275    let sys_flag = get_i32_checked(byte_buffer)?;
276    msg_ext.set_sys_flag(sys_flag);
277
278    // 9 BORNTIMESTAMP
279    let born_time_stamp = get_i64_checked(byte_buffer)?;
280    msg_ext.set_born_timestamp(born_time_stamp);
281
282    // 10 BORNHOST
283    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    // 11 STORETIMESTAMP
301    let store_timestamp = get_i64_checked(byte_buffer)?;
302    msg_ext.set_store_timestamp(store_timestamp);
303
304    // 12 STOREHOST
305    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    // 13 RECONSUMETIMES
323    let reconsume_times = get_i32_checked(byte_buffer)?;
324    msg_ext.set_reconsume_times(reconsume_times);
325
326    // 14 Prepared Transaction Offset
327    let prepared_transaction_offset = get_i64_checked(byte_buffer)?;
328    msg_ext.set_prepared_transaction_offset(prepared_transaction_offset);
329
330    // 15 BODY
331    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        // Handle reading and processing body
338        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    // 16 TOPIC
358    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    // 17 properties
365    let properties_length = get_i16_checked(byte_buffer)?;
366    if properties_length < 0 {
367        return None;
368    }
369    if properties_length > 0 {
370        // Handle reading and processing properties
371        let properties = split_to_checked(byte_buffer, properties_length as usize)?;
372        if !is_set_properties_string {
373            //can optimize later
374            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    //let mut all_size = 0;
413    for message in messages {
414        let message_bytes = encode_message(message);
415        //all_size += message_bytes.len();
416        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 // 1 TOTALSIZE
430             + 4 // 2 MAGICCOD
431             + 4 // 3 BODYCRC
432             + 4 // 4 FLAG
433             + 4 + body_len // 4 BODY
434             + 2 + properties_length;
435
436    let mut bytes = BytesMut::with_capacity(store_size);
437
438    // 1 TOTALSIZE
439    bytes.put_i32(store_size as i32);
440
441    // 2 MAGICCODE
442    bytes.put_i32(0);
443
444    // 3 BODYCRC
445    bytes.put_u32(0);
446
447    // 4 FLAG
448    bytes.put_i32(message.flag());
449
450    // 5 BODY
451    bytes.put_i32(body_len as i32);
452    bytes.put_slice(body);
453
454    // 6 PROPERTIES
455    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        //MessageAccessor::set_properties(&mut
500        // message_client_ext,message.get_properties().clone()); messageClientExt.
501        // setBody(message.getBody())
502        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    // 1 TOTALSIZE
530    let store_size = get_i32_checked(buffer)?;
531    if store_size <= 0 {
532        return None;
533    }
534
535    // 2 MAGICCODE
536    let _ = get_i32_checked(buffer)?;
537
538    // 3 BODYCRC
539    let _ = get_i32_checked(buffer)?;
540
541    // 4 FLAG
542    let flag = get_i32_checked(buffer)?;
543
544    // 5 BODY
545    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    // 6 properties
552    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    //string_to_message_properties(Some(&String::from_utf8_lossy(properties.as_ref()).
558    // to_string()));
559    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 // 1 TOTALSIZE
647             + 4 // 2 MAGICCODE
648             + 4 // 3 BODYCRC
649             + 4 // 4 QUEUEID
650             + 4 // 5 FLAG
651             + 8 // 6 QUEUEOFFSET
652             + 8 // 7 PHYSICALOFFSET
653             + 4 // 8 SYSFLAG
654             + 8 // 9 BORNTIMESTAMP
655             + born_host_length // 10 BORNHOST
656             + 8 // 11 STORETIMESTAMP
657             + store_host_address_length // 12 STOREHOSTADDRESS
658             + 4 // 13 RECONSUMETIMES
659             + 8 // 14 Prepared Transaction Offset
660             + 4 + body_len // 14 BODY
661             + 1 + topic_len // 15 TOPIC
662             + 2 + properties_length // 16 propertiesLength
663    };
664    let mut byte_buffer = BytesMut::with_capacity(store_size);
665
666    // 1 TOTALSIZE
667    byte_buffer.put_i32(store_size as i32);
668
669    // 2 MAGICCODE
670    byte_buffer.put_i32(MESSAGE_MAGIC_CODE);
671
672    // 3 BODYCRC
673    byte_buffer.put_u32(message_ext.body_crc);
674
675    // 4 QUEUEID
676    byte_buffer.put_i32(message_ext.queue_id);
677
678    // 5 FLAG
679    byte_buffer.put_i32(message_ext.message.flag());
680
681    // 6 QUEUEOFFSET
682    byte_buffer.put_i64(message_ext.queue_offset);
683
684    // 7 PHYSICALOFFSET
685    byte_buffer.put_i64(message_ext.commit_log_offset);
686
687    // 8 SYSFLAG
688    byte_buffer.put_i32(message_ext.sys_flag);
689
690    // 9 BORNTIMESTAMP
691    byte_buffer.put_i64(message_ext.born_timestamp);
692
693    // 10 BORNHOST
694
695    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    // 11 STORETIMESTAMP
704    byte_buffer.put_i64(message_ext.store_timestamp);
705
706    // 12 STOREHOST
707
708    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    // 13 RECONSUMETIMES
717    byte_buffer.put_i32(message_ext.reconsume_times);
718
719    // 14 Prepared Transaction Offset
720    byte_buffer.put_i64(message_ext.prepared_transaction_offset);
721
722    // 15 BODY
723    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    // 16 TOPIC
731    byte_buffer.put_u8(topic_len as u8);
732    byte_buffer.put_slice(topic);
733
734    // 17 properties
735    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 // 1 TOTALSIZE
768             + 4 // 2 MAGICCODE
769             + 4 // 3 BODYCRC
770             + 4 // 4 QUEUEID
771             + 4 // 5 FLAG
772             + 8 // 6 QUEUEOFFSET
773             + 8 // 7 PHYSICALOFFSET
774             + 4 // 8 SYSFLAG
775             + 8 // 9 BORNTIMESTAMP
776             + born_host_length // 10 BORNHOST
777             + 4 // 11 RECONSUMETIMES
778             + 8 // 12 Prepared Transaction Offset
779             + 4 + body_len // 13 BODY
780             + 1 + topic_len // 14 TOPIC
781             + 2 + properties_length // 15 propertiesLength
782    };
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    // 1 TOTALSIZE
791    byte_buffer.put_i32(store_size as i32);
792
793    // 2 MAGICCODE
794    byte_buffer.put_i32(MESSAGE_MAGIC_CODE);
795
796    // 3 BODYCRC
797    byte_buffer.put_u32(message_ext.body_crc);
798
799    // 4 QUEUEID
800    byte_buffer.put_i32(message_ext.queue_id);
801
802    // 5 FLAG
803    byte_buffer.put_i32(message_ext.message.flag());
804
805    // 6 QUEUEOFFSET
806    byte_buffer.put_i64(message_ext.queue_offset);
807
808    // 7 PHYSICALOFFSET
809    byte_buffer.put_i64(message_ext.commit_log_offset);
810
811    // 8 SYSFLAG
812    byte_buffer.put_i32(message_ext.sys_flag);
813
814    // 9 BORNTIMESTAMP
815    byte_buffer.put_i64(message_ext.born_timestamp);
816
817    // 10 BORNHOST
818
819    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    // 11 RECONSUMETIMES
827    byte_buffer.put_i32(message_ext.reconsume_times);
828
829    // 12 Prepared Transaction Offset
830    byte_buffer.put_i64(message_ext.prepared_transaction_offset);
831
832    // 13 BODY
833    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    // 14 TOPIC
841    byte_buffer.put_i16(topic_len as i16);
842    byte_buffer.put_slice(topics);
843
844    // 15 properties
845    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    // Ensure we have enough bytes to read SYSFLAG and MAGICCODE.
868    if bytes.len() < SYSFLAG_POSITION + 4 {
869        return None;
870    }
871
872    // Read sysFlag and magicCode using fixed positions.
873    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    // Determine address lengths.
881    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    // Calculate the bodySizePosition as in Java.
893    let body_size_position = 4   // TOTALSIZE
894        + 4   // MAGICCODE
895        + 4   // BODYCRC
896        + 4   // QUEUEID
897        + 4   // FLAG
898        + 8   // QUEUEOFFSET
899        + 8   // PHYSICALOFFSET
900        + 4   // SYSFLAG
901        + 8   // BORNTIMESTAMP
902        + bornhost_length // BORNHOST
903        + 8   // STORETIMESTAMP
904        + storehost_address_length // STOREHOSTADDRESS
905        + 4   // RECONSUMETIMES
906        + 8; // Prepared Transaction Offset
907
908    if bytes.len() < body_size_position + 4 {
909        return None;
910    }
911
912    // Read the body size stored as an int.
913    let body_size = BigEndian::read_i32(&bytes[body_size_position..body_size_position + 4]) as usize;
914
915    // Compute the topic length position.
916    let topic_length_position = body_size_position + 4 + body_size;
917    if bytes.len() < topic_length_position {
918        return None;
919    }
920
921    // Create a Cursor over the slice starting at the topic length position.
922    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    // Calculate the properties position.
929    let properties_position = topic_length_position + topic_length_size + topic_length;
930    if bytes.len() < properties_position + 2 {
931        return None;
932    }
933
934    // Read a short (2 bytes) as propertiesLength.
935    let properties_length = BigEndian::read_i16(&bytes[properties_position..properties_position + 2]);
936
937    // Advance past the short value.
938    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}