1 // Copyright (C) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 use std::ffi::{c_char, c_int, c_uint, c_ulonglong, CString};
15
16 /// Length limit for the name of a HiSysEventParam.
17 const MAX_LENGTH_OF_PARAM_NAME: usize = 49;
18
19 /// This type represent to HiSysEventParamValue defined in C.
20 #[repr(C)]
21 #[derive(Copy, Clone)]
22 pub union HiSysEventParamValue {
23 /// Bool.
24 pub b_: bool,
25
26 /// Int8_t.
27 pub i8_: i8,
28
29 /// Uint8_t.
30 pub u8_: u8,
31
32 /// Int16_t.
33 pub i16_: i16,
34
35 /// Uint16_t.
36 pub u16_: u16,
37
38 /// Int32_t.
39 pub i32_: i32,
40
41 /// Uint32_t.
42 pub u32_: u32,
43
44 /// Int64_t.
45 pub i64_: i64,
46
47 /// Uint64_t.
48 pub u64_: u64,
49
50 /// Float.
51 pub f32_: f32,
52
53 /// Double.
54 pub f64_: f64,
55
56 /// String.
57 pub char_ptr_: *const c_char,
58
59 /// Array.
60 pub void_ptr_: *const (),
61 }
62
63 /// This type represent to HiSysEventParamType defined in C.
64 #[derive(Copy, Clone)]
65 pub enum HiSysEventParamType {
66 /// Invalid type.
67 Invalid = 0,
68
69 /// Bool type.
70 Bool,
71
72 /// Int8_t type.
73 Int8,
74
75 /// Uint8_t type.
76 Uint8,
77
78 /// Int16_t type.
79 Int16,
80
81 /// Uint16_t type.
82 Uint16,
83
84 /// Int32_t type.
85 Int32,
86
87 /// Uint32_t type.
88 Uint32,
89
90 /// Int64_t type.
91 Int64,
92
93 /// Uint64_t type.
94 Uint64,
95
96 /// Float type.
97 Float,
98
99 /// Double type.
100 Double,
101
102 /// String type.
103 ParamTypeString,
104
105 /// Bool array type.
106 BoolArray,
107
108 /// Int8_t array type.
109 Int8Array,
110
111 /// Uint8_t array type.
112 Uint8Array,
113
114 /// Int16_t array type.
115 Int16Array,
116
117 /// Uint16_t array type.
118 Uint16Array,
119
120 /// Int32_t array type.
121 Int32Array,
122
123 /// Unt32_t array type.
124 Uint32Array,
125
126 /// Int64_t array type.
127 Int64Array,
128
129 /// Uint16_t array type.
130 Uint64Array,
131
132 /// Float array type.
133 FloatArray,
134
135 /// Double array type.
136 DoubleArray,
137
138 /// String array type.
139 ParamTypeStringArray,
140 }
141
142 /// Definition customized param.
143 pub struct HiSysEventParam<'a> {
144 /// Param key
145 pub param_name: &'a str,
146
147 /// Param type
148 pub param_type: HiSysEventParamType,
149
150 /// Param value
151 pub param_value: HiSysEventParamValue,
152
153 /// Size of param value
154 pub array_size: usize,
155 }
156
157 /// This type represent to HiSysEventParamWrapper defined in C.
158 #[repr(C)]
159 #[derive(Copy, Clone)]
160 struct HiSysEventParamWrapper {
161 /// Param name.
162 pub param_name: [u8; MAX_LENGTH_OF_PARAM_NAME],
163
164 /// Param type.
165 pub param_type: c_int,
166
167 /// Param value.
168 pub param_value: HiSysEventParamValue,
169
170 /// Length of a param with array type.
171 pub array_size: c_uint,
172 }
173
174 /// Parse type and length of a variable.
175 #[allow(dead_code)]
parse_type_len<T>(_: T) -> (&'static str, usize)176 pub fn parse_type_len<T>(_: T) -> (&'static str, usize) {
177 let mut value_type = std::any::type_name::<T>();
178 let mut bytes = value_type.as_bytes();
179 if bytes[0] == b'&' {
180 value_type = &value_type[1..];
181 bytes = value_type.as_bytes();
182 }
183 if bytes[0] != b'[' {
184 // not a array
185 if bytes[0] == b'&' {
186 // reference
187 return (&value_type[1..], 0);
188 } else {
189 return (value_type, 0);
190 }
191 }
192 // array
193 let mut val_end: usize = 0;
194 let mut len_start: usize = 0;
195 for (i, &item) in bytes.iter().enumerate() {
196 if item == b';' {
197 val_end = i;
198 }
199 if item == b' ' {
200 len_start = i + 1;
201 break;
202 }
203 }
204 let array_len = value_type[len_start..(bytes.len() - 1)]
205 .parse::<usize>()
206 .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())
228 as *const c_int as *const (),
229 },
230 array_size: str_arr.len(),
231 }
232 }
233
234 /// Write system event.
write( event_domain: &str, event_name: &str, event_type: c_int, event_params: &[HiSysEventParam], ) -> i32235 pub(crate) fn write(
236 event_domain: &str,
237 event_name: &str,
238 event_type: c_int,
239 event_params: &[HiSysEventParam],
240 ) -> i32 {
241 let mut params_wrapper: Vec<HiSysEventParamWrapper> = vec![];
242 for i in 0..event_params.len() {
243 params_wrapper.push(HiSysEventParamWrapper {
244 param_name: [0; MAX_LENGTH_OF_PARAM_NAME],
245 param_type: event_params[i].param_type as i32 as c_int,
246 param_value: event_params[i].param_value,
247 array_size: event_params[i].array_size as c_uint,
248 });
249 crate::utils::trans_slice_to_array(
250 event_params[i].param_name,
251 &mut params_wrapper[i].param_name,
252 );
253 }
254 let func = CString::new(crate::function!()).expect("Need a valid function name");
255 let domain = CString::new(event_domain).expect("Need a valid domain name");
256 let event_name = CString::new(event_name).expect("Need a valid event name");
257 // Safty: call C ffi border function, all risks are under control.
258 unsafe {
259 HiSysEventWriteWrapper(
260 func.as_ptr() as *const c_char,
261 line!() as c_ulonglong,
262 domain.as_ptr() as *const c_char,
263 event_name.as_ptr() as *const c_char,
264 event_type,
265 params_wrapper.as_mut_ptr(),
266 event_params.len() as c_uint,
267 )
268 }
269 }
270
271 extern "C" {
272 /// 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_int273 fn HiSysEventWriteWrapper(
274 func: *const c_char,
275 line: c_ulonglong,
276 domain: *const c_char,
277 name: *const c_char,
278 event_type: c_int,
279 params: *const HiSysEventParamWrapper,
280 size: c_uint,
281 ) -> c_int;
282 }
283