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 use std::ffi::{CString, c_char, c_int, c_uint, c_ulonglong};
17
18 /// Length limit for the name of a HiSysEventParam.
19 const MAX_LENGTH_OF_PARAM_NAME: usize = 49;
20
21 /// This type represent to HiSysEventParamValue defined in C.
22 #[repr(C)]
23 #[derive(Copy, Clone)]
24 pub union HiSysEventParamValue {
25 /// Bool.
26 pub b_: bool,
27
28 /// Int8_t.
29 pub i8_: i8,
30
31 /// Uint8_t.
32 pub u8_: u8,
33
34 /// Int16_t.
35 pub i16_: i16,
36
37 /// Uint16_t.
38 pub u16_: u16,
39
40 /// Int32_t.
41 pub i32_: i32,
42
43 /// Uint32_t.
44 pub u32_: u32,
45
46 /// Int64_t.
47 pub i64_: i64,
48
49 /// Uint64_t.
50 pub u64_: u64,
51
52 /// Float.
53 pub f32_: f32,
54
55 /// Double.
56 pub f64_: f64,
57
58 /// String.
59 pub char_ptr_: *const c_char,
60
61 /// Array.
62 pub void_ptr_: *const (),
63 }
64
65 /// This type represent to HiSysEventParamType defined in C.
66 #[derive(Copy, Clone)]
67 pub enum HiSysEventParamType {
68 /// Invalid type.
69 Invalid = 0,
70
71 /// Bool type.
72 Bool,
73
74 /// Int8_t type.
75 Int8,
76
77 /// Uint8_t type.
78 Uint8,
79
80 /// Int16_t type.
81 Int16,
82
83 /// Uint16_t type.
84 Uint16,
85
86 /// Int32_t type.
87 Int32,
88
89 /// Uint32_t type.
90 Uint32,
91
92 /// Int64_t type.
93 Int64,
94
95 /// Uint64_t type.
96 Uint64,
97
98 /// Float type.
99 Float,
100
101 /// Double type.
102 Double,
103
104 /// String type.
105 ParamTypeString,
106
107 /// Bool array type.
108 BoolArray,
109
110 /// Int8_t array type.
111 Int8Array,
112
113 /// Uint8_t array type.
114 Uint8Array,
115
116 /// Int16_t array type.
117 Int16Array,
118
119 /// Uint16_t array type.
120 Uint16Array,
121
122 /// Int32_t array type.
123 Int32Array,
124
125 /// Unt32_t array type.
126 Uint32Array,
127
128 /// Int64_t array type.
129 Int64Array,
130
131 /// Uint16_t array type.
132 Uint64Array,
133
134 /// Float array type.
135 FloatArray,
136
137 /// Double array type.
138 DoubleArray,
139
140 /// String array type.
141 ParamTypeStringArray,
142 }
143
144 /// Definition customized param.
145 pub struct HiSysEventParam<'a> {
146 /// Param key
147 pub param_name: &'a str,
148
149 /// Param type
150 pub param_type: HiSysEventParamType,
151
152 /// Param value
153 pub param_value: HiSysEventParamValue,
154
155 /// Size of param value
156 pub array_size: usize,
157 }
158
159 /// This type represent to HiSysEventParamWrapper defined in C.
160 #[repr(C)]
161 #[derive(Copy, Clone)]
162 struct HiSysEventParamWrapper {
163 /// Param name.
164 pub param_name: [c_char; MAX_LENGTH_OF_PARAM_NAME],
165
166 /// Param type.
167 pub param_type: c_int,
168
169 /// Param value.
170 pub param_value: HiSysEventParamValue,
171
172 /// Length of a param with array type.
173 pub array_size: c_uint,
174 }
175
176 /// Parse type and length of a variable.
177 #[allow(dead_code)]
parse_type_len<T>(_: T) -> (&'static str, usize)178 pub fn parse_type_len<T>(_: T) -> (&'static str, usize) {
179 let mut value_type = std::any::type_name::<T>();
180 let mut bytes = value_type.as_bytes();
181 if bytes[0] == b'&' {
182 value_type = &value_type[1..];
183 bytes = value_type.as_bytes();
184 }
185 if bytes[0] != b'[' {
186 // not a array
187 if bytes[0] == b'&' {
188 // reference
189 return (&value_type[1..], 0);
190 } else {
191 return (value_type, 0);
192 }
193 }
194 // array
195 let mut val_end: usize = 0;
196 let mut len_start: usize = 0;
197 for (i, &item) in bytes.iter().enumerate() {
198 if item == b';' {
199 val_end = i;
200 }
201 if item == b' ' {
202 len_start = i + 1;
203 break;
204 }
205 }
206 let array_len = value_type[len_start..(bytes.len() - 1)].parse::<usize>().unwrap();
207 if bytes[1] == b'&' {
208 // reference
209 (&value_type[2..val_end], array_len)
210 } else {
211 (&value_type[1..val_end], array_len)
212 }
213 }
214
215 /// Build hisysevent param with string array type.
216 #[allow(dead_code)]
build_string_arrays<'a>(param_name: &'a str, str_arr: &[&'a str]) -> HiSysEventParam<'a>217 pub fn build_string_arrays<'a>(param_name: &'a str, str_arr: &[&'a str]) -> HiSysEventParam<'a> {
218 let mut dest: Vec<*const c_char> = vec![];
219 for &item in str_arr {
220 let str_wrapper = CString::new(item).expect("Need a valid value with &str type.");
221 dest.push(str_wrapper.into_raw() as *const c_char);
222 }
223 HiSysEventParam {
224 param_name,
225 param_type: HiSysEventParamType::ParamTypeStringArray,
226 param_value: HiSysEventParamValue {
227 void_ptr_: std::boxed::Box::<[*const c_char]>::into_raw(dest.into_boxed_slice()) as *const c_int as *const (),
228 },
229 array_size: str_arr.len(),
230 }
231 }
232
233 /// Write system event.
write(event_domain: &str, event_name: &str, event_type: c_int, event_params: &[HiSysEventParam]) -> i32234 pub(crate) fn write(event_domain: &str, event_name: &str, event_type: c_int, event_params: &[HiSysEventParam]) -> i32 {
235 let mut params_wrapper: Vec<HiSysEventParamWrapper> = vec![];
236 for i in 0..event_params.len() {
237 params_wrapper.push(HiSysEventParamWrapper {
238 param_name: [0; MAX_LENGTH_OF_PARAM_NAME],
239 param_type: event_params[i].param_type as i32 as c_int,
240 param_value: event_params[i].param_value,
241 array_size: event_params[i].array_size as c_uint,
242 });
243 crate::utils::trans_slice_to_array(event_params[i].param_name, &mut params_wrapper[i].param_name);
244 }
245 let func = CString::new(crate::function!()).expect("Need a valid function name");
246 let domain = CString::new(event_domain).expect("Need a valid domain name");
247 let event_name = CString::new(event_name).expect("Need a valid event name");
248 // Safty: call C ffi border function, all risks are under control.
249 unsafe {
250 HiSysEventWriteWrapper(
251 func.as_ptr() as *const c_char,
252 line!() as c_ulonglong,
253 domain.as_ptr() as *const c_char,
254 event_name.as_ptr() as *const c_char,
255 event_type,
256 params_wrapper.as_mut_ptr(),
257 event_params.len() as c_uint
258 )
259 }
260 }
261
262 extern "C" {
263 /// ffi border function.
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_int264 fn HiSysEventWriteWrapper(func: *const c_char, line: c_ulonglong, domain: *const c_char,
265 name: *const c_char, event_type: c_int, params: *const HiSysEventParamWrapper,
266 size: c_uint) -> c_int;
267 }