rocketmq_protocol/protocol/
remoting_command.rs1use std::fmt;
16use std::sync::atomic::AtomicI32;
17use std::sync::atomic::Ordering;
18use std::sync::Arc;
19
20#[cfg(test)]
21use std::collections::HashMap;
22
23use bytes::Bytes;
24use cheetah_string::CheetahString;
25use serde::ser::SerializeMap;
26use serde::Deserialize;
27use serde::Deserializer;
28use serde::Serialize;
29use serde::Serializer;
30
31use super::RemotingCommandType;
32use super::SerializeType;
33use crate::protocol::command_custom_header::CommandCustomHeader;
34use crate::protocol::header_codec::BinaryHeaderFields;
35use crate::protocol::header_codec::JsonHeaderFields;
36use crate::protocol::LanguageCode;
37
38#[cfg(test)]
39use crate::protocol::command_custom_header::FromMap;
40#[cfg(test)]
41use bytes::BufMut;
42#[cfg(test)]
43use bytes::BytesMut;
44
45pub const SERIALIZE_TYPE_PROPERTY: &str = "rocketmq.serialize.type";
46pub const SERIALIZE_TYPE_ENV: &str = "ROCKETMQ_SERIALIZE_TYPE";
47pub const REMOTING_VERSION_KEY: &str = "rocketmq.remoting.version";
48
49static REQUEST_ID: AtomicI32 = AtomicI32::new(0);
50
51#[cfg(test)]
52std::thread_local! {
53 static REQUEST_ID_GENERATIONS: std::cell::Cell<usize> = const { std::cell::Cell::new(0) };
54}
55
56#[cfg(test)]
57pub(crate) fn request_id_generation_count() -> usize {
58 REQUEST_ID_GENERATIONS.get()
59}
60
61#[inline]
62fn next_request_id_from(counter: &AtomicI32) -> i32 {
63 counter.fetch_add(1, Ordering::AcqRel)
64}
65
66#[inline]
67fn next_request_id() -> i32 {
68 #[cfg(test)]
69 REQUEST_ID_GENERATIONS.set(REQUEST_ID_GENERATIONS.get() + 1);
70 next_request_id_from(&REQUEST_ID)
71}
72
73mod accessors;
74mod constructors;
75mod custom_header;
76mod decode;
77mod encode;
78mod extension_fields;
79mod flags;
80mod frame;
81mod legacy_api;
82
83use extension_fields::ExtensionFields;
84
85fn serialize_ext_fields<S>(ext_fields: &ExtensionFields, serializer: S) -> Result<S::Ok, S::Error>
86where
87 S: Serializer,
88{
89 let Some(ext_fields) = ext_fields.as_map() else {
90 return serializer.serialize_none();
91 };
92 let mut entries = ext_fields.iter().collect::<Vec<_>>();
93 entries.sort_unstable_by(|(left, _), (right, _)| left.as_str().cmp(right.as_str()));
94 let mut map = serializer.serialize_map(Some(entries.len()))?;
95 for (key, value) in entries {
96 map.serialize_entry(key, value)?;
97 }
98 map.end()
99}
100
101fn deserialize_ext_fields<'de, D>(deserializer: D) -> Result<ExtensionFields, D::Error>
102where
103 D: Deserializer<'de>,
104{
105 Option::<JsonHeaderFields>::deserialize(deserializer)
106 .map(|fields| fields.map_or_else(ExtensionFields::default, ExtensionFields::from_json_raw))
107}
108
109#[derive(Serialize, Deserialize)]
110pub struct RemotingCommand {
111 code: i32,
112 language: LanguageCode,
113 version: i32,
114 opaque: i32,
115
116 flag: i32,
122 remark: Option<CheetahString>,
123
124 #[serde(
125 rename = "extFields",
126 default,
127 serialize_with = "serialize_ext_fields",
128 deserialize_with = "deserialize_ext_fields"
129 )]
130 ext_fields: ExtensionFields,
131
132 #[serde(skip)]
133 body: Option<Bytes>,
134 #[serde(skip)]
135 suspended: bool,
136 #[serde(skip)]
137 command_custom_header: Option<Arc<Box<dyn CommandCustomHeader + Send + Sync + 'static>>>,
138 #[serde(skip)]
139 custom_header_to_net: bool,
140 #[serde(rename = "serializeTypeCurrentRPC")]
141 serialize_type: SerializeType,
142}
143
144impl Clone for RemotingCommand {
145 fn clone(&self) -> Self {
146 Self {
147 code: self.code,
148 language: self.language,
149 version: self.version,
150 opaque: self.opaque,
151 flag: self.flag,
152 remark: self.remark.clone(),
153 ext_fields: self.ext_fields.clone(),
154 body: self.body.clone(),
155 suspended: self.suspended,
156 command_custom_header: self.command_custom_header.clone(),
157 custom_header_to_net: self.custom_header_to_net,
158 serialize_type: self.serialize_type,
159 }
160 }
161}
162
163impl fmt::Display for RemotingCommand {
164 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
165 write!(
166 f,
167 "RemotingCommand [code={}, language={}, version={}, opaque={}, flag(B)={:b}, remark={}, extFields={:?}, \
168 serializeTypeCurrentRPC={}]",
169 self.code,
170 self.language,
171 self.version,
172 self.opaque,
173 self.flag,
174 self.remark.as_ref().unwrap_or(&CheetahString::default()),
175 self.ext_fields,
176 self.serialize_type
177 )
178 }
179}
180
181impl Default for RemotingCommand {
182 fn default() -> Self {
183 Self::with_resolved_defaults(0, SerializeType::JSON)
184 }
185}
186
187#[inline]
189pub fn parse_header_length(size: i32) -> usize {
190 (size & 0x00FFFFFF) as usize
191}
192
193#[inline]
195pub fn mark_protocol_type(source: i32, serialize_type: SerializeType) -> i32 {
196 ((serialize_type.get_code() as i32) << 24) | (source & 0x00FFFFFF)
197}
198
199#[inline]
201pub fn parse_serialize_type(size: i32) -> rocketmq_error::Result<SerializeType> {
202 let code = (size >> 24) as u8;
203 SerializeType::value_of(code).ok_or_else(|| crate::error::unsupported_encoding(code))
204}
205
206#[cfg(test)]
207mod tests;