xref: /base/msdp/device_status/rust/utils/src/macros.rs (revision f857971d)
1/*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16//! Several macros
17
18#![allow(dead_code)]
19
20/// macro define_enum can be used to define enum type, which is associated with several helper functions.
21#[macro_export]
22macro_rules! define_enum {
23    {
24        $name:ident {
25            $( $item:ident ), *
26        }
27    } => {
28        /// enum $name
29        #[allow(dead_code)]
30        #[derive(Hash, PartialEq, Eq, Clone)]
31        #[repr(u32)]
32        pub enum $name {
33            $(
34                /// variant $item
35                $item,
36            )*
37        }
38
39        impl TryFrom<u32> for $name {
40            type Error = FusionErrorCode;
41            fn try_from(code: u32) -> std::result::Result<Self, Self::Error> {
42                match code {
43                    $(
44                        _ if code == Self::$item as u32 => {
45                            Ok(Self::$item)
46                        }
47                    )*
48                    _ => {
49                        Err(FusionErrorCode::Fail)
50                    }
51                }
52            }
53        }
54
55        impl ipc_rust::Serialize for $name {
56            fn serialize(&self, parcel: &mut ipc_rust::BorrowedMsgParcel<'_>) -> ipc_rust::IpcResult<()> {
57                match self {
58                    $(
59                        Self::$item => {
60                            (Self::$item as u32).serialize(parcel)
61                        }
62                    )*
63                }
64            }
65        }
66
67        impl ipc_rust::Deserialize for $name {
68            fn deserialize(parcel: &ipc_rust::BorrowedMsgParcel<'_>) -> ipc_rust::IpcResult<Self> {
69                match u32::deserialize(parcel) {
70                    Ok(val) => {
71                        match $name::try_from(val) {
72                            Ok(e) => {
73                                Ok(e)
74                            }
75                            Err(_) => {
76                                Err(ipc_rust::IpcStatusCode::InvalidValue)
77                            }
78                        }
79                    }
80                    Err(err) => {
81                        Err(err)
82                    }
83                }
84            }
85        }
86    };
87}
88
89/// Helper to log the enter and leave of function calls.
90pub struct InnerFunctionTracer<'a> {
91    log: Box<dyn Fn(&str, &str)>,
92    func_name: &'a str
93}
94
95impl<'a> InnerFunctionTracer<'a> {
96    /// Construct a new instance of [`InnerFunctionTracer`].
97    pub fn new(log: Box<dyn Fn(&str, &str)>, func_name: &'a str) -> Self {
98        log(func_name, "enter");
99        Self {
100            log, func_name
101        }
102    }
103}
104
105impl<'a> Drop for InnerFunctionTracer<'a> {
106    fn drop(&mut self) {
107        (self.log)(self.func_name, "leave");
108    }
109}
110
111/// Log in `DEBUG` level the enter and leave of function calls.
112#[macro_export]
113macro_rules! call_debug_enter {
114    (
115        $func_name: literal
116    ) => {
117        let __inner_function_tracer__ = $crate::InnerFunctionTracer::new(
118            Box::new(|func_name: &str, action: &str| {
119                hilog_rust::debug!(LOG_LABEL, "In {}: {}", @public(func_name), @public(action));
120            }),
121            $func_name
122        );
123    };
124}
125
126/// Log in `INFO` level the enter and leave of function calls.
127#[macro_export]
128macro_rules! call_info_trace {
129    (
130        $func_name: literal
131    ) => {
132        let __inner_function_tracer__ = $crate::InnerFunctionTracer::new(
133            Box::new(|func_name: &str, action: &str| {
134                hilog_rust::info!(LOG_LABEL, "In {}: {}", @public(func_name), @public(action));
135            }),
136            $func_name
137        );
138    };
139}
140
141/// When the expression is an `Err` variant, "log(C function name) failed" is recorded and return the error.
142#[macro_export]
143macro_rules! err_log {
144    ($expr:expr, $log:expr) => {
145        match $expr {
146            Ok(val) => val,
147            Err(err) => {
148                error!(LOG_LABEL, "{} failed", $log);
149                return Err(err);
150            }
151        }
152    };
153}