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