/* * Copyright (C) 2023 Huawei Device Co., Ltd. * Licensed 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. */ use std::ffi::{CString, c_char, c_int, c_uint, c_ulonglong}; /// Length limit for the name of a HiSysEventParam. const MAX_LENGTH_OF_PARAM_NAME: usize = 49; /// This type represent to HiSysEventParamValue defined in C. #[repr(C)] #[derive(Copy, Clone)] pub union HiSysEventParamValue { /// Bool. pub b_: bool, /// Int8_t. pub i8_: i8, /// Uint8_t. pub u8_: u8, /// Int16_t. pub i16_: i16, /// Uint16_t. pub u16_: u16, /// Int32_t. pub i32_: i32, /// Uint32_t. pub u32_: u32, /// Int64_t. pub i64_: i64, /// Uint64_t. pub u64_: u64, /// Float. pub f32_: f32, /// Double. pub f64_: f64, /// String. pub char_ptr_: *const c_char, /// Array. pub void_ptr_: *const (), } /// This type represent to HiSysEventParamType defined in C. #[derive(Copy, Clone)] pub enum HiSysEventParamType { /// Invalid type. Invalid = 0, /// Bool type. Bool, /// Int8_t type. Int8, /// Uint8_t type. Uint8, /// Int16_t type. Int16, /// Uint16_t type. Uint16, /// Int32_t type. Int32, /// Uint32_t type. Uint32, /// Int64_t type. Int64, /// Uint64_t type. Uint64, /// Float type. Float, /// Double type. Double, /// String type. ParamTypeString, /// Bool array type. BoolArray, /// Int8_t array type. Int8Array, /// Uint8_t array type. Uint8Array, /// Int16_t array type. Int16Array, /// Uint16_t array type. Uint16Array, /// Int32_t array type. Int32Array, /// Unt32_t array type. Uint32Array, /// Int64_t array type. Int64Array, /// Uint16_t array type. Uint64Array, /// Float array type. FloatArray, /// Double array type. DoubleArray, /// String array type. ParamTypeStringArray, } /// Definition customized param. pub struct HiSysEventParam<'a> { /// Param key pub param_name: &'a str, /// Param type pub param_type: HiSysEventParamType, /// Param value pub param_value: HiSysEventParamValue, /// Size of param value pub array_size: usize, } /// This type represent to HiSysEventParamWrapper defined in C. #[repr(C)] #[derive(Copy, Clone)] struct HiSysEventParamWrapper { /// Param name. pub param_name: [u8; MAX_LENGTH_OF_PARAM_NAME], /// Param type. pub param_type: c_int, /// Param value. pub param_value: HiSysEventParamValue, /// Length of a param with array type. pub array_size: c_uint, } /// Parse type and length of a variable. #[allow(dead_code)] pub fn parse_type_len(_: T) -> (&'static str, usize) { let mut value_type = std::any::type_name::(); let mut bytes = value_type.as_bytes(); if bytes[0] == b'&' { value_type = &value_type[1..]; bytes = value_type.as_bytes(); } if bytes[0] != b'[' { // not a array if bytes[0] == b'&' { // reference return (&value_type[1..], 0); } else { return (value_type, 0); } } // array let mut val_end: usize = 0; let mut len_start: usize = 0; for (i, &item) in bytes.iter().enumerate() { if item == b';' { val_end = i; } if item == b' ' { len_start = i + 1; break; } } let array_len = value_type[len_start..(bytes.len() - 1)].parse::().unwrap(); if bytes[1] == b'&' { // reference (&value_type[2..val_end], array_len) } else { (&value_type[1..val_end], array_len) } } /// Build hisysevent param with string array type. #[allow(dead_code)] pub fn build_string_arrays<'a>(param_name: &'a str, str_arr: &[&'a str]) -> HiSysEventParam<'a> { let mut dest: Vec<*const c_char> = vec![]; for &item in str_arr { let str_wrapper = CString::new(item).expect("Need a valid value with &str type."); dest.push(str_wrapper.into_raw() as *const c_char); } HiSysEventParam { param_name, param_type: HiSysEventParamType::ParamTypeStringArray, param_value: HiSysEventParamValue { void_ptr_: std::boxed::Box::<[*const c_char]>::into_raw(dest.into_boxed_slice()) as *const c_int as *const (), }, array_size: str_arr.len(), } } /// Write system event. pub(crate) fn write(event_domain: &str, event_name: &str, event_type: c_int, event_params: &[HiSysEventParam]) -> i32 { let mut params_wrapper: Vec = vec![]; for i in 0..event_params.len() { params_wrapper.push(HiSysEventParamWrapper { param_name: [0; MAX_LENGTH_OF_PARAM_NAME], param_type: event_params[i].param_type as i32 as c_int, param_value: event_params[i].param_value, array_size: event_params[i].array_size as c_uint, }); crate::utils::trans_slice_to_array(event_params[i].param_name, &mut params_wrapper[i].param_name); } let func = CString::new(crate::function!()).expect("Need a valid function name"); let domain = CString::new(event_domain).expect("Need a valid domain name"); let event_name = CString::new(event_name).expect("Need a valid event name"); // Safty: call C ffi border function, all risks are under control. unsafe { HiSysEventWriteWrapper( func.as_ptr() as *const c_char, line!() as c_ulonglong, domain.as_ptr() as *const c_char, event_name.as_ptr() as *const c_char, event_type, params_wrapper.as_mut_ptr(), event_params.len() as c_uint ) } } extern "C" { /// ffi border function. fn HiSysEventWriteWrapper(func: *const c_char, line: c_ulonglong, domain: *const c_char, name: *const c_char, event_type: c_int, params: *const HiSysEventParamWrapper, size: c_uint) -> c_int; }