use cheetah_string::CheetahString;
use rocketmq_macros::RequestHeaderCodecV2;
use serde::Deserialize;
use serde::Serialize;
use crate::protocol::header::namesrv::topic_operation_header::TopicRequestHeader;
#[derive(Serialize, Deserialize, Debug, Default, RequestHeaderCodecV2)]
#[serde(rename_all = "camelCase")]
pub struct ReplyMessageRequestHeader {
#[required]
pub producer_group: CheetahString,
#[required]
pub topic: CheetahString,
#[required]
pub default_topic: CheetahString,
#[required]
pub default_topic_queue_nums: i32,
#[required]
pub queue_id: i32,
#[required]
pub sys_flag: i32,
#[required]
pub born_timestamp: i64,
#[required]
pub flag: i32,
pub properties: Option<CheetahString>,
pub reconsume_times: Option<i32>,
pub unit_mode: Option<bool>,
#[required]
pub born_host: CheetahString,
#[required]
pub store_host: CheetahString,
#[required]
pub store_timestamp: i64,
#[serde(flatten)]
pub topic_request: Option<TopicRequestHeader>,
}
#[cfg(test)]
mod reply_message_request_header_tests {
use std::collections::HashMap;
use super::*;
use crate::protocol::command_custom_header::CommandCustomHeader;
use crate::protocol::command_custom_header::FromMap;
#[test]
fn deserialize_from_map_with_all_fields_populates_struct_correctly() {
let mut map: HashMap<CheetahString, CheetahString> = HashMap::new();
map.insert("producerGroup".into(), "test_producer_group".into());
map.insert("topic".into(), "test_topic".into());
map.insert("defaultTopic".into(), "test_default_topic".into());
map.insert("defaultTopicQueueNums".into(), "10".into());
map.insert("queueId".into(), "1".into());
map.insert("sysFlag".into(), "0".into());
map.insert("flag".into(), "0".into());
map.insert("bornTimestamp".into(), "1622547800".into());
map.insert("bornHost".into(), "test_born_host".into());
map.insert("storeHost".into(), "test_store_host".into());
map.insert("storeTimestamp".into(), "1622547800".into());
map.insert("unitMode".into(), "true".into());
let header: ReplyMessageRequestHeader = <ReplyMessageRequestHeader as FromMap>::from(&map).unwrap();
assert_eq!(header.topic, "test_topic");
assert_eq!(header.producer_group, "test_producer_group");
assert_eq!(header.default_topic, "test_default_topic");
assert_eq!(header.default_topic_queue_nums, 10);
assert_eq!(header.queue_id, 1);
assert_eq!(header.sys_flag, 0);
assert_eq!(header.flag, 0);
assert_eq!(header.born_timestamp, 1622547800);
assert_eq!(header.born_host, "test_born_host");
assert_eq!(header.store_host, "test_store_host");
assert_eq!(header.store_timestamp, 1622547800);
assert_eq!(header.properties, None);
assert_eq!(header.reconsume_times, None);
assert_eq!(header.unit_mode, Some(true));
}
#[test]
fn deserialize_from_map_with_invalid_number_fields_returns_none() {
let mut map = HashMap::new();
map.insert("producerGroup".into(), "test_producer_group".into());
map.insert("topic".into(), "test_topic".into());
map.insert("defaultTopic".into(), "test_default_topic".into());
map.insert("defaultTopicQueueNums".into(), "invalid".into());
let header: Result<ReplyMessageRequestHeader, rocketmq_error::RocketMQError> =
<ReplyMessageRequestHeader as FromMap>::from(&map);
assert!(header.is_err());
}
#[test]
fn serialize_header_to_map() {
let header = ReplyMessageRequestHeader {
topic: "test_topic".into(),
producer_group: "test_producer_group".into(),
default_topic: "test_default_topic".into(),
default_topic_queue_nums: 10,
queue_id: 1,
flag: 2,
sys_flag: 0,
born_timestamp: 1622547800,
born_host: "test_born_host".into(),
store_host: "test_store_host".into(),
store_timestamp: 1622547800,
properties: Some("test_properties".into()),
reconsume_times: Some(1),
unit_mode: Some(true),
topic_request: None,
};
let map: HashMap<CheetahString, CheetahString> = header.to_map().unwrap();
assert_eq!(map.get("topic").unwrap(), "test_topic");
assert_eq!(map.get("producerGroup").unwrap(), "test_producer_group");
assert_eq!(map.get("defaultTopicQueueNums").unwrap(), "10");
assert_eq!(map.get("bornTimestamp").unwrap(), "1622547800");
assert!(!map.contains_key("topicRequest"));
assert_eq!(map.get("queueId").unwrap(), "1");
assert_eq!(map.get("sysFlag").unwrap(), "0");
assert_eq!(map.get("bornHost").unwrap(), "test_born_host");
assert_eq!(map.get("storeHost").unwrap(), "test_store_host");
assert_eq!(map.get("storeTimestamp").unwrap(), "1622547800");
assert_eq!(map.get("flag").unwrap(), "2");
assert_eq!(map.get("properties").unwrap(), "test_properties");
assert_eq!(map.get("reconsumeTimes").unwrap(), "1");
assert_eq!(map.get("unitMode").unwrap(), "true");
}
#[test]
fn serialize_header_to_map_with_topic_request_header_includes_nested_fields() {
let topic_request_header = TopicRequestHeader::default();
let header = ReplyMessageRequestHeader {
topic: "test_topic".into(),
producer_group: "test_producer_group".into(),
default_topic: "test_default_topic".into(),
default_topic_queue_nums: 10,
queue_id: 1,
flag: 2,
sys_flag: 0,
born_timestamp: 1622547800,
born_host: "test_born_host".into(),
store_host: "test_store_host".into(),
store_timestamp: 1622547800,
properties: Some("test_properties".into()),
reconsume_times: Some(1),
unit_mode: Some(true),
topic_request: Some(topic_request_header),
};
let map: HashMap<CheetahString, CheetahString> = header.to_map().unwrap();
assert!(!map.contains_key("nestedField"));
}
}