rocketmq_protocol/protocol/remoting_command/
decode.rs1use bytes::BytesMut;
16
17use super::parse_header_length;
18use super::parse_serialize_type;
19use super::RemotingCommand;
20use super::SerializeType;
21use crate::rocketmq_serializable::RocketMQSerializable;
22
23mod json;
24
25use json::try_decode_json_header;
26use json::try_decode_json_header_bytes;
27
28impl RemotingCommand {
29 #[inline]
34 pub fn decode(src: &mut BytesMut) -> rocketmq_error::Result<Option<RemotingCommand>> {
35 Self::decode_with_max_frame_bytes(src, 16 * 1024 * 1024 + 4)
36 }
37
38 #[inline]
46 pub fn decode_with_max_frame_bytes(
47 src: &mut BytesMut,
48 max_frame_bytes: usize,
49 ) -> rocketmq_error::Result<Option<RemotingCommand>> {
50 const FRAME_HEADER_SIZE: usize = 4;
51 const SERIALIZE_TYPE_SIZE: usize = 4;
52 const MIN_PAYLOAD_SIZE: usize = SERIALIZE_TYPE_SIZE; let available = src.len();
55
56 if available < FRAME_HEADER_SIZE {
58 return Ok(None);
59 }
60
61 let announced_size = i32::from_be_bytes([src[0], src[1], src[2], src[3]]);
63 let total_size = usize::try_from(announced_size).map_err(|_| {
64 crate::error::serialization_decode_failed(
65 "remoting_command",
66 format!("Invalid negative frame size {announced_size}"),
67 )
68 })?;
69 let full_frame_size = total_size.checked_add(FRAME_HEADER_SIZE).ok_or_else(|| {
70 crate::error::serialization_decode_failed(
71 "remoting_command",
72 format!("Frame size {total_size} overflows the wire envelope"),
73 )
74 })?;
75
76 if full_frame_size > max_frame_bytes {
77 return Err(crate::error::serialization_decode_failed(
78 "remoting_command",
79 format!("Wire frame size {full_frame_size} exceeds configured limit {max_frame_bytes}"),
80 ));
81 }
82
83 if available < full_frame_size {
85 return Ok(None);
86 }
87
88 if total_size < MIN_PAYLOAD_SIZE {
90 return Err(crate::error::serialization_decode_failed(
91 "remoting_command",
92 format!("Invalid total_size {total_size}, minimum required is {MIN_PAYLOAD_SIZE}"),
93 ));
94 }
95
96 let frame_data = src.split_to(full_frame_size);
100 let ori_header_length = i32::from_be_bytes([frame_data[4], frame_data[5], frame_data[6], frame_data[7]]);
101 let header_length = parse_header_length(ori_header_length);
102
103 if header_length > total_size - SERIALIZE_TYPE_SIZE {
105 return Err(crate::error::serialization_decode_failed(
106 "remoting_command",
107 format!("Invalid header length {header_length}, total size {total_size}"),
108 ));
109 }
110
111 let protocol_type = parse_serialize_type(ori_header_length)?;
112 let frame = frame_data.freeze();
113 let header_start = FRAME_HEADER_SIZE + SERIALIZE_TYPE_SIZE;
114 let header_end = header_start + header_length;
115 let mut cmd = match protocol_type {
116 SerializeType::ROCKETMQ => {
117 RocketMQSerializable::rocket_mq_protocol_decode_bytes(frame.slice(header_start..header_end))?
118 }
119 SerializeType::JSON => {
120 if let Some(cmd) = try_decode_json_header_bytes(frame.slice(header_start..header_end)) {
121 cmd
122 } else {
123 let mut header_data = BytesMut::from(&frame[header_start..header_end]);
127 Self::decode_json_header_fallback(&mut header_data, header_length)?
128 }
129 }
130 };
131 cmd.set_serialize_type_ref(protocol_type);
132 if header_end < frame.len() {
133 cmd.set_body_mut_ref(frame.slice(header_end..));
134 }
135 Ok(Some(cmd))
136 }
137
138 #[cold]
139 #[inline(never)]
140 fn decode_json_header_fallback(
141 src: &mut BytesMut,
142 _header_length: usize,
143 ) -> rocketmq_error::Result<RemotingCommand> {
144 #[cfg(feature = "simd")]
145 {
146 let mut slice = src.split_to(_header_length).to_vec();
147 simd_json::from_slice::<RemotingCommand>(&mut slice)
148 .map_err(|error| crate::error::serialization_source("decode", "json", error))
149 }
150
151 #[cfg(not(feature = "simd"))]
152 {
153 serde_json::from_slice::<RemotingCommand>(src)
154 .map_err(|error| crate::error::serialization_source("decode", "json", error))
155 }
156 }
157
158 #[inline]
160 pub fn header_decode(
161 src: &mut BytesMut,
162 header_length: usize,
163 type_: SerializeType,
164 ) -> rocketmq_error::Result<Option<RemotingCommand>> {
165 match type_ {
166 SerializeType::JSON => {
167 if let Some(cmd) = try_decode_json_header(src, header_length) {
168 return Ok(Some(cmd.set_serialize_type(SerializeType::JSON)));
169 }
170 let cmd = Self::decode_json_header_fallback(src, header_length)?;
171 Ok(Some(cmd.set_serialize_type(SerializeType::JSON)))
172 }
173 SerializeType::ROCKETMQ => {
174 let cmd = RocketMQSerializable::rocket_mq_protocol_decode(src, header_length)?;
176 Ok(Some(cmd.set_serialize_type(SerializeType::ROCKETMQ)))
177 }
178 }
179 }
180}