11401458bSopenharmony_ci/*
21401458bSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd.
31401458bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
41401458bSopenharmony_ci * you may not use this file except in compliance with the License.
51401458bSopenharmony_ci * You may obtain a copy of the License at
61401458bSopenharmony_ci *
71401458bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
81401458bSopenharmony_ci *
91401458bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
101401458bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
111401458bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121401458bSopenharmony_ci * See the License for the specific language governing permissions and
131401458bSopenharmony_ci * limitations under the License.
141401458bSopenharmony_ci */
151401458bSopenharmony_ci
161401458bSopenharmony_ciuse std::ffi::{CString, c_char, c_int, c_uint, c_ulonglong};
171401458bSopenharmony_ci
181401458bSopenharmony_ci/// Length limit for the name of a HiSysEventParam.
191401458bSopenharmony_ciconst MAX_LENGTH_OF_PARAM_NAME: usize = 49;
201401458bSopenharmony_ci
211401458bSopenharmony_ci/// This type represent to HiSysEventParamValue defined in C.
221401458bSopenharmony_ci#[repr(C)]
231401458bSopenharmony_ci#[derive(Copy, Clone)]
241401458bSopenharmony_cipub union HiSysEventParamValue {
251401458bSopenharmony_ci    /// Bool.
261401458bSopenharmony_ci    pub b_: bool,
271401458bSopenharmony_ci
281401458bSopenharmony_ci    /// Int8_t.
291401458bSopenharmony_ci    pub i8_: i8,
301401458bSopenharmony_ci
311401458bSopenharmony_ci    /// Uint8_t.
321401458bSopenharmony_ci    pub u8_: u8,
331401458bSopenharmony_ci
341401458bSopenharmony_ci    /// Int16_t.
351401458bSopenharmony_ci    pub i16_: i16,
361401458bSopenharmony_ci
371401458bSopenharmony_ci    /// Uint16_t.
381401458bSopenharmony_ci    pub u16_: u16,
391401458bSopenharmony_ci
401401458bSopenharmony_ci    /// Int32_t.
411401458bSopenharmony_ci    pub i32_: i32,
421401458bSopenharmony_ci
431401458bSopenharmony_ci    /// Uint32_t.
441401458bSopenharmony_ci    pub u32_: u32,
451401458bSopenharmony_ci
461401458bSopenharmony_ci    /// Int64_t.
471401458bSopenharmony_ci    pub i64_: i64,
481401458bSopenharmony_ci
491401458bSopenharmony_ci    /// Uint64_t.
501401458bSopenharmony_ci    pub u64_: u64,
511401458bSopenharmony_ci
521401458bSopenharmony_ci    /// Float.
531401458bSopenharmony_ci    pub f32_: f32,
541401458bSopenharmony_ci
551401458bSopenharmony_ci    /// Double.
561401458bSopenharmony_ci    pub f64_: f64,
571401458bSopenharmony_ci
581401458bSopenharmony_ci    /// String.
591401458bSopenharmony_ci    pub char_ptr_: *const c_char,
601401458bSopenharmony_ci
611401458bSopenharmony_ci    /// Array.
621401458bSopenharmony_ci    pub void_ptr_: *const (),
631401458bSopenharmony_ci}
641401458bSopenharmony_ci
651401458bSopenharmony_ci/// This type represent to HiSysEventParamType defined in C.
661401458bSopenharmony_ci#[derive(Copy, Clone)]
671401458bSopenharmony_cipub enum HiSysEventParamType {
681401458bSopenharmony_ci    /// Invalid type.
691401458bSopenharmony_ci    Invalid = 0,
701401458bSopenharmony_ci
711401458bSopenharmony_ci    /// Bool type.
721401458bSopenharmony_ci    Bool,
731401458bSopenharmony_ci
741401458bSopenharmony_ci    /// Int8_t type.
751401458bSopenharmony_ci    Int8,
761401458bSopenharmony_ci
771401458bSopenharmony_ci    /// Uint8_t type.
781401458bSopenharmony_ci    Uint8,
791401458bSopenharmony_ci
801401458bSopenharmony_ci    /// Int16_t type.
811401458bSopenharmony_ci    Int16,
821401458bSopenharmony_ci
831401458bSopenharmony_ci    /// Uint16_t type.
841401458bSopenharmony_ci    Uint16,
851401458bSopenharmony_ci
861401458bSopenharmony_ci    /// Int32_t type.
871401458bSopenharmony_ci    Int32,
881401458bSopenharmony_ci
891401458bSopenharmony_ci    /// Uint32_t type.
901401458bSopenharmony_ci    Uint32,
911401458bSopenharmony_ci
921401458bSopenharmony_ci    /// Int64_t type.
931401458bSopenharmony_ci    Int64,
941401458bSopenharmony_ci
951401458bSopenharmony_ci    /// Uint64_t type.
961401458bSopenharmony_ci    Uint64,
971401458bSopenharmony_ci
981401458bSopenharmony_ci    /// Float type.
991401458bSopenharmony_ci    Float,
1001401458bSopenharmony_ci
1011401458bSopenharmony_ci    /// Double type.
1021401458bSopenharmony_ci    Double,
1031401458bSopenharmony_ci
1041401458bSopenharmony_ci    /// String type.
1051401458bSopenharmony_ci    ParamTypeString,
1061401458bSopenharmony_ci
1071401458bSopenharmony_ci    /// Bool array type.
1081401458bSopenharmony_ci    BoolArray,
1091401458bSopenharmony_ci
1101401458bSopenharmony_ci    /// Int8_t array type.
1111401458bSopenharmony_ci    Int8Array,
1121401458bSopenharmony_ci
1131401458bSopenharmony_ci    /// Uint8_t array type.
1141401458bSopenharmony_ci    Uint8Array,
1151401458bSopenharmony_ci
1161401458bSopenharmony_ci    /// Int16_t array type.
1171401458bSopenharmony_ci    Int16Array,
1181401458bSopenharmony_ci
1191401458bSopenharmony_ci    /// Uint16_t array type.
1201401458bSopenharmony_ci    Uint16Array,
1211401458bSopenharmony_ci
1221401458bSopenharmony_ci    /// Int32_t array type.
1231401458bSopenharmony_ci    Int32Array,
1241401458bSopenharmony_ci
1251401458bSopenharmony_ci    /// Unt32_t array type.
1261401458bSopenharmony_ci    Uint32Array,
1271401458bSopenharmony_ci
1281401458bSopenharmony_ci    /// Int64_t array type.
1291401458bSopenharmony_ci    Int64Array,
1301401458bSopenharmony_ci
1311401458bSopenharmony_ci    /// Uint16_t array type.
1321401458bSopenharmony_ci    Uint64Array,
1331401458bSopenharmony_ci
1341401458bSopenharmony_ci    /// Float array type.
1351401458bSopenharmony_ci    FloatArray,
1361401458bSopenharmony_ci
1371401458bSopenharmony_ci    /// Double array type.
1381401458bSopenharmony_ci    DoubleArray,
1391401458bSopenharmony_ci
1401401458bSopenharmony_ci    /// String array type.
1411401458bSopenharmony_ci    ParamTypeStringArray,
1421401458bSopenharmony_ci}
1431401458bSopenharmony_ci
1441401458bSopenharmony_ci/// Definition customized param.
1451401458bSopenharmony_cipub struct HiSysEventParam<'a> {
1461401458bSopenharmony_ci    /// Param key
1471401458bSopenharmony_ci    pub param_name: &'a str,
1481401458bSopenharmony_ci
1491401458bSopenharmony_ci    /// Param type
1501401458bSopenharmony_ci    pub param_type: HiSysEventParamType,
1511401458bSopenharmony_ci
1521401458bSopenharmony_ci    /// Param value
1531401458bSopenharmony_ci    pub param_value: HiSysEventParamValue,
1541401458bSopenharmony_ci
1551401458bSopenharmony_ci    /// Size of param value
1561401458bSopenharmony_ci    pub array_size: usize,
1571401458bSopenharmony_ci}
1581401458bSopenharmony_ci
1591401458bSopenharmony_ci/// This type represent to HiSysEventParamWrapper defined in C.
1601401458bSopenharmony_ci#[repr(C)]
1611401458bSopenharmony_ci#[derive(Copy, Clone)]
1621401458bSopenharmony_cistruct HiSysEventParamWrapper {
1631401458bSopenharmony_ci    /// Param name.
1641401458bSopenharmony_ci    pub param_name: [u8; MAX_LENGTH_OF_PARAM_NAME],
1651401458bSopenharmony_ci
1661401458bSopenharmony_ci    /// Param type.
1671401458bSopenharmony_ci    pub param_type: c_int,
1681401458bSopenharmony_ci
1691401458bSopenharmony_ci    /// Param value.
1701401458bSopenharmony_ci    pub param_value: HiSysEventParamValue,
1711401458bSopenharmony_ci
1721401458bSopenharmony_ci    /// Length of a param with array type.
1731401458bSopenharmony_ci    pub array_size: c_uint,
1741401458bSopenharmony_ci}
1751401458bSopenharmony_ci
1761401458bSopenharmony_ci/// Parse type and length of a variable.
1771401458bSopenharmony_ci#[allow(dead_code)]
1781401458bSopenharmony_cipub fn parse_type_len<T>(_: T) -> (&'static str, usize) {
1791401458bSopenharmony_ci    let mut value_type = std::any::type_name::<T>();
1801401458bSopenharmony_ci    let mut bytes = value_type.as_bytes();
1811401458bSopenharmony_ci    if bytes[0] == b'&' {
1821401458bSopenharmony_ci        value_type = &value_type[1..];
1831401458bSopenharmony_ci        bytes = value_type.as_bytes();
1841401458bSopenharmony_ci    }
1851401458bSopenharmony_ci    if bytes[0] != b'[' {
1861401458bSopenharmony_ci        // not a array
1871401458bSopenharmony_ci        if bytes[0] == b'&' {
1881401458bSopenharmony_ci            // reference
1891401458bSopenharmony_ci            return (&value_type[1..], 0);
1901401458bSopenharmony_ci        } else {
1911401458bSopenharmony_ci            return (value_type, 0);
1921401458bSopenharmony_ci        }
1931401458bSopenharmony_ci    }
1941401458bSopenharmony_ci    // array
1951401458bSopenharmony_ci    let mut val_end: usize = 0;
1961401458bSopenharmony_ci    let mut len_start: usize = 0;
1971401458bSopenharmony_ci    for (i, &item) in bytes.iter().enumerate() {
1981401458bSopenharmony_ci        if item == b';' {
1991401458bSopenharmony_ci            val_end = i;
2001401458bSopenharmony_ci        }
2011401458bSopenharmony_ci        if item == b' ' {
2021401458bSopenharmony_ci            len_start = i + 1;
2031401458bSopenharmony_ci            break;
2041401458bSopenharmony_ci        }
2051401458bSopenharmony_ci    }
2061401458bSopenharmony_ci    let array_len = value_type[len_start..(bytes.len() - 1)].parse::<usize>().unwrap();
2071401458bSopenharmony_ci    if bytes[1] == b'&' {
2081401458bSopenharmony_ci        // reference
2091401458bSopenharmony_ci        (&value_type[2..val_end], array_len)
2101401458bSopenharmony_ci    } else {
2111401458bSopenharmony_ci        (&value_type[1..val_end], array_len)
2121401458bSopenharmony_ci    }
2131401458bSopenharmony_ci}
2141401458bSopenharmony_ci
2151401458bSopenharmony_ci/// Build hisysevent param with string array type.
2161401458bSopenharmony_ci#[allow(dead_code)]
2171401458bSopenharmony_cipub fn build_string_arrays<'a>(param_name: &'a str, str_arr: &[&'a str]) -> HiSysEventParam<'a> {
2181401458bSopenharmony_ci    let mut dest: Vec<*const c_char> = vec![];
2191401458bSopenharmony_ci    for &item in str_arr {
2201401458bSopenharmony_ci        let str_wrapper = CString::new(item).expect("Need a valid value with &str type.");
2211401458bSopenharmony_ci        dest.push(str_wrapper.into_raw() as *const c_char);
2221401458bSopenharmony_ci    }
2231401458bSopenharmony_ci    HiSysEventParam {
2241401458bSopenharmony_ci        param_name,
2251401458bSopenharmony_ci        param_type: HiSysEventParamType::ParamTypeStringArray,
2261401458bSopenharmony_ci        param_value: HiSysEventParamValue {
2271401458bSopenharmony_ci            void_ptr_: std::boxed::Box::<[*const c_char]>::into_raw(dest.into_boxed_slice()) as *const c_int as *const (),
2281401458bSopenharmony_ci        },
2291401458bSopenharmony_ci        array_size: str_arr.len(),
2301401458bSopenharmony_ci    }
2311401458bSopenharmony_ci}
2321401458bSopenharmony_ci
2331401458bSopenharmony_ci/// Write system event.
2341401458bSopenharmony_cipub(crate) fn write(event_domain: &str, event_name: &str, event_type: c_int, event_params: &[HiSysEventParam]) -> i32 {
2351401458bSopenharmony_ci    let mut params_wrapper: Vec<HiSysEventParamWrapper> = vec![];
2361401458bSopenharmony_ci    for i in 0..event_params.len() {
2371401458bSopenharmony_ci        params_wrapper.push(HiSysEventParamWrapper {
2381401458bSopenharmony_ci            param_name: [0; MAX_LENGTH_OF_PARAM_NAME],
2391401458bSopenharmony_ci            param_type: event_params[i].param_type as i32 as c_int,
2401401458bSopenharmony_ci            param_value: event_params[i].param_value,
2411401458bSopenharmony_ci            array_size: event_params[i].array_size as c_uint,
2421401458bSopenharmony_ci        });
2431401458bSopenharmony_ci        crate::utils::trans_slice_to_array(event_params[i].param_name, &mut params_wrapper[i].param_name);
2441401458bSopenharmony_ci    }
2451401458bSopenharmony_ci    let func = CString::new(crate::function!()).expect("Need a valid function name");
2461401458bSopenharmony_ci    let domain = CString::new(event_domain).expect("Need a valid domain name");
2471401458bSopenharmony_ci    let event_name = CString::new(event_name).expect("Need a valid event name");
2481401458bSopenharmony_ci    // Safty: call C ffi border function, all risks are under control.
2491401458bSopenharmony_ci    unsafe {
2501401458bSopenharmony_ci        HiSysEventWriteWrapper(
2511401458bSopenharmony_ci            func.as_ptr() as *const c_char,
2521401458bSopenharmony_ci            line!() as c_ulonglong,
2531401458bSopenharmony_ci            domain.as_ptr() as *const c_char,
2541401458bSopenharmony_ci            event_name.as_ptr() as *const c_char,
2551401458bSopenharmony_ci            event_type,
2561401458bSopenharmony_ci            params_wrapper.as_mut_ptr(),
2571401458bSopenharmony_ci            event_params.len() as c_uint
2581401458bSopenharmony_ci        )
2591401458bSopenharmony_ci    }
2601401458bSopenharmony_ci}
2611401458bSopenharmony_ci
2621401458bSopenharmony_ciextern "C" {
2631401458bSopenharmony_ci    /// ffi border function.
2641401458bSopenharmony_ci    fn HiSysEventWriteWrapper(func: *const c_char, line: c_ulonglong, domain: *const c_char,
2651401458bSopenharmony_ci        name: *const c_char, event_type: c_int, params: *const HiSysEventParamWrapper,
2661401458bSopenharmony_ci        size: c_uint) -> c_int;
2671401458bSopenharmony_ci}
268