blob: 22e5a667798420fb9371ba22150bb569256fff20 [file] [log] [blame]
/* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/// This macro does 4 expansions in one go:
///
/// 1) The `#[enum_dispatch(ServerCommandHandler)] pub enum ServerCommand`
/// with all variants.
/// 2) The `from_code_and_payload(code, payload)` function that matches each code.
/// 3) The `to_bytes()` function that matches each variant.
/// 4) The `validate()` function that matches each variant.
#[macro_export]
macro_rules! define_server_command_enum {
(
$(
// Macro pattern:
// variant name inner type numeric code display string show_payload?
$variant:ident ( $ty:ty ), $code:ident, $display_str:expr, $show_payload:expr
);* $(;)?
) => {
#[enum_dispatch(ServerCommandHandler)]
#[derive(Debug, PartialEq, EnumString, EnumIter)]
pub enum ServerCommand {
$(
$variant($ty),
)*
}
impl ServerCommand {
/// Constructs a `ServerCommand` from its numeric code and payload.
pub fn from_code_and_payload(code: u32, payload: Bytes) -> Result<Self, IggyError> {
match code {
$(
$code => Ok(ServerCommand::$variant(
<$ty>::from_bytes(payload)?
)),
)*
_ => {
error!("Invalid server command: {}", code);
Err(IggyError::InvalidCommand)
}
}
}
/// Constructs a ServerCommand from its numeric code by reading from the provided async reader.
pub async fn from_code_and_reader(
code: u32,
sender: &mut SenderKind,
length: u32,
) -> Result<Self, IggyError> {
match code {
$(
$code => Ok(ServerCommand::$variant(
<$ty as BinaryServerCommand>::from_sender(sender, code, length).await?
)),
)*
_ => Err(IggyError::InvalidCommand),
}
}
/// Converts the command into raw bytes.
pub fn to_bytes(&self) -> Bytes {
match self {
$(
ServerCommand::$variant(payload) => as_bytes(payload),
)*
}
}
/// Validate the command by delegating to the inner command's implementation.
pub fn validate(&self) -> Result<(), IggyError> {
match self {
$(
ServerCommand::$variant(cmd) => <$ty as iggy_common::Validatable<iggy_common::IggyError>>::validate(cmd),
)*
}
}
}
impl std::fmt::Display for ServerCommand {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
$(
// If $show_payload is true, we display the command name + payload;
// otherwise, we just display the command name.
ServerCommand::$variant(payload) => {
if $show_payload {
write!(formatter, "{}|{payload:?}", $display_str)
} else {
write!(formatter, "{}", $display_str)
}
},
)*
}
}
}
};
}