rocketmq_remoting/protocol/
command_custom_header.rs

1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17use std::any::Any;
18use std::collections::HashMap;
19
20use cheetah_string::CheetahString;
21
22use crate::rocketmq_serializable::RocketMQSerializable;
23
24pub trait CommandCustomHeader: AsAny {
25    /// Checks the fields of the implementing type.  
26    ///  
27    /// Returns a `Result` indicating whether the fields are valid or not.  
28    /// If the fields are valid, the `Ok` variant is returned with an empty `()` value.  
29    /// If the fields are invalid, an `Err` variant is returned with an associated `Error` value.  
30    fn check_fields(&self) -> anyhow::Result<(), anyhow::Error> {
31        Ok(())
32    }
33
34    /// Converts the implementing type to a map.  
35    ///  
36    /// Returns an `Option` that contains a `HashMap` of string keys and string values,  
37    /// representing the implementing type's fields.  
38    /// If the conversion is successful, a non-empty map is returned.  
39    /// If the conversion fails, `None` is returned.  
40    fn to_map(&self) -> Option<HashMap<CheetahString, CheetahString>>;
41
42    /// Writes the provided `key` to the `out` buffer if the `value` is not empty.
43    ///
44    /// # Arguments
45    ///
46    /// * `out` - A mutable reference to a `BytesMut` buffer where the `key` will be written.
47    /// * `key` - A string slice that represents the key to be written.
48    /// * `value` - A string slice that represents the value associated with the key.
49    ///
50    /// # Behavior
51    ///
52    /// If `value` is not empty, the function will write the `key` to the `out` buffer twice,
53    /// first with a short length prefix and then with a long length prefix.
54    fn write_if_not_null(&self, out: &mut bytes::BytesMut, key: &str, value: &str) {
55        if !value.is_empty() {
56            RocketMQSerializable::write_str(out, true, key);
57            RocketMQSerializable::write_str(out, false, value);
58        }
59    }
60
61    /// A placeholder function for fast encoding.
62    ///
63    /// This function currently does nothing and can be overridden by implementing types.
64    fn encode_fast(&mut self, _out: &mut bytes::BytesMut) {}
65
66    /// A placeholder function for fast decoding.
67    ///
68    /// This function currently does nothing and can be overridden by implementing types.
69    ///
70    /// # Arguments
71    ///
72    /// * `_fields` - A reference to a `HashMap` that contains the fields to be decoded.
73    fn decode_fast(
74        &mut self,
75        _fields: &HashMap<CheetahString, CheetahString>,
76    ) -> rocketmq_error::RocketMQResult<()> {
77        Ok(())
78    }
79
80    /// Indicates whether the implementing type supports fast codec.
81    ///
82    /// # Returns
83    ///
84    /// This function returns `false` by default, indicating that the implementing type does not
85    /// support fast codec. This can be overridden by implementing types.
86    fn support_fast_codec(&self) -> bool {
87        false
88    }
89
90    /// Retrieves the value associated with the specified field from the provided map.
91    ///
92    /// # Arguments
93    ///
94    /// * `map` - A reference to a `HashMap` containing `CheetahString` keys and values.
95    /// * `field` - A reference to a `CheetahString` representing the field to retrieve.
96    ///
97    /// # Returns
98    ///
99    /// * `Ok(CheetahString)` - If the field is found in the map, returns the associated value.
100    /// * `Err(RocketMQError::Serialization)` - If the field is not found in the map, returns an
101    ///   error indicating the field is required.
102    ///
103    /// # Errors
104    ///
105    /// This function returns a `SerializationError::DecodeFailed` if the specified field is
106    /// not found in the map.
107    #[inline(always)]
108    fn get_and_check_not_none(
109        &self,
110        map: &HashMap<CheetahString, CheetahString>,
111        field: &CheetahString,
112    ) -> rocketmq_error::RocketMQResult<CheetahString> {
113        match map.get(field) {
114            Some(value) => Ok(value.clone()),
115            None => Err(rocketmq_error::RocketMQError::Serialization(
116                rocketmq_error::SerializationError::DecodeFailed {
117                    format: "header",
118                    message: format!("The field {field} is required."),
119                },
120            )),
121        }
122    }
123}
124
125pub trait AsAny: Any {
126    fn as_any_mut(&mut self) -> &mut dyn Any;
127
128    fn as_any(&self) -> &dyn Any;
129}
130
131impl<T: CommandCustomHeader> AsAny for T {
132    fn as_any_mut(&mut self) -> &mut dyn Any {
133        self
134    }
135
136    fn as_any(&self) -> &dyn Any {
137        self
138    }
139}
140
141pub trait FromMap {
142    type Error: From<rocketmq_error::RocketMQError>;
143
144    type Target;
145    /// Converts the implementing type from a map.
146    ///
147    /// Returns an instance of `Self::Target` that is created from the provided map.
148    fn from(map: &HashMap<CheetahString, CheetahString>) -> Result<Self::Target, Self::Error>;
149}