1 /*
2 * Copyright (C) 2022 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 #include "napi_parser_utils.h"
17
18 #include <string>
19 #include <vector>
20
21 #include "napi_async_callback.h"
22
23 namespace OHOS {
24 namespace Bluetooth {
25
26 // shall check object type is napi_object before, if it's other type, return false
27 // If the 'name' field is not exist, or napi function call error, return false
NapiIsObjectPropertyExist(napi_env env,napi_value object,const char * name)28 static bool NapiIsObjectPropertyExist(napi_env env, napi_value object, const char *name)
29 {
30 auto status = NapiIsObject(env, object);
31 if (status != napi_ok) {
32 HILOGE("expect object");
33 return false;
34 }
35 bool exist = false;
36 status = napi_has_named_property(env, object, name, &exist);
37 if (status != napi_ok) {
38 HILOGE("Get object property failed, name: %{public}s", name);
39 return false;
40 }
41 return exist;
42 }
43
NapiParseGattService(napi_env env,napi_value object,NapiGattService & outService)44 napi_status NapiParseGattService(napi_env env, napi_value object, NapiGattService &outService)
45 {
46 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "isPrimary", "characteristics",
47 "includeServices"}));
48
49 std::string uuid {};
50 bool isPrimary = true;
51 std::vector<NapiBleCharacteristic> characteristics {};
52 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
53 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", uuid));
54 NAPI_BT_CALL_RETURN(NapiParseObjectBoolean(env, object, "isPrimary", isPrimary));
55 NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "characteristics", characteristics));
56 if (NapiIsObjectPropertyExist(env, object, "includeServices")) {
57 std::vector<NapiGattService> includeServices {};
58 NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "includeServices", includeServices));
59 outService.includeServices = std::move(includeServices);
60 }
61 outService.serviceUuid = UUID::FromString(uuid);
62 outService.isPrimary = isPrimary;
63 outService.characteristics = std::move(characteristics);
64 return napi_ok;
65 }
66
67 namespace {
68 const NapiGattPermission DEFAULT_GATT_PERMISSIONS = {
69 .readable = true,
70 .writeable = true,
71 };
72 const NapiGattProperties DEFAULT_GATT_PROPERTIES = {
73 .write = true,
74 .writeNoResponse = true,
75 .read = true,
76 };
ConvertGattPermissions(const NapiGattPermission & napiPermissions)77 uint16_t ConvertGattPermissions(const NapiGattPermission &napiPermissions)
78 {
79 uint16_t permissions = 0;
80 if (napiPermissions.readable) {
81 permissions |= static_cast<uint16_t>(GattPermission::READABLE);
82 }
83 if (napiPermissions.writeable) {
84 permissions |= static_cast<uint16_t>(GattPermission::WRITEABLE);
85 }
86 if (napiPermissions.readEncrypted) {
87 permissions |= static_cast<uint16_t>(GattPermission::READ_ENCRYPTED_MITM);
88 }
89 if (napiPermissions.writeEncrypted) {
90 permissions |= static_cast<uint16_t>(GattPermission::WRITE_ENCRYPTED_MITM);
91 }
92 return permissions;
93 }
ConvertGattProperties(const NapiGattProperties & napiProperties)94 uint16_t ConvertGattProperties(const NapiGattProperties &napiProperties)
95 {
96 uint16_t properties = 0;
97 if (napiProperties.read) {
98 properties |= static_cast<uint16_t>(GattCharacteristic::READ);
99 }
100 if (napiProperties.write) {
101 properties |= static_cast<uint16_t>(GattCharacteristic::WRITE);
102 }
103 if (napiProperties.writeNoResponse) {
104 properties |= static_cast<uint16_t>(GattCharacteristic::WRITE_WITHOUT_RESPONSE);
105 }
106 if (napiProperties.notify) {
107 properties |= static_cast<uint16_t>(GattCharacteristic::NOTIFY);
108 }
109 if (napiProperties.indicate) {
110 properties |= static_cast<uint16_t>(GattCharacteristic::INDICATE);
111 }
112 return properties;
113 }
114 } // namespace {}
115
NapiParseGattCharacteristic(napi_env env,napi_value object,NapiBleCharacteristic & outCharacteristic)116 napi_status NapiParseGattCharacteristic(napi_env env, napi_value object, NapiBleCharacteristic &outCharacteristic)
117 {
118 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
119 "characteristicValue", "descriptors", "properties", "permissions"}));
120
121 std::string serviceUuid {};
122 std::string characterUuid {};
123 std::vector<uint8_t> characterValue {};
124 std::vector<NapiBleDescriptor> descriptors {};
125 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
126 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
127 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
128 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "characteristicValue", characterValue));
129 NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "descriptors", descriptors));
130
131 NapiGattProperties properties = DEFAULT_GATT_PROPERTIES;
132 if (NapiIsObjectPropertyExist(env, object, "properties")) {
133 NAPI_BT_CALL_RETURN(NapiParseObjectGattProperties(env, object, "properties", properties));
134 }
135 NapiGattPermission permissions = DEFAULT_GATT_PERMISSIONS;
136 if (NapiIsObjectPropertyExist(env, object, "permissions")) {
137 NAPI_BT_CALL_RETURN(NapiParseObjectGattPermissions(env, object, "permissions", permissions));
138 }
139
140 outCharacteristic.serviceUuid = UUID::FromString(serviceUuid);
141 outCharacteristic.characteristicUuid = UUID::FromString(characterUuid);
142 outCharacteristic.characteristicValue = std::move(characterValue);
143 outCharacteristic.descriptors = std::move(descriptors);
144 outCharacteristic.properties = ConvertGattProperties(properties);
145 outCharacteristic.permissions = ConvertGattPermissions(permissions);
146 return napi_ok;
147 }
148
NapiParseGattDescriptor(napi_env env,napi_value object,NapiBleDescriptor & outDescriptor)149 napi_status NapiParseGattDescriptor(napi_env env, napi_value object, NapiBleDescriptor &outDescriptor)
150 {
151 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
152 "descriptorUuid", "descriptorValue", "permissions"}));
153
154 std::string serviceUuid {};
155 std::string characterUuid {};
156 std::string descriptorUuid {};
157 std::vector<uint8_t> descriptorValue {};
158 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
159 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
160 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
161 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "descriptorUuid", descriptorUuid));
162 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "descriptorValue", descriptorValue));
163
164 NapiGattPermission permissions = DEFAULT_GATT_PERMISSIONS;
165 if (NapiIsObjectPropertyExist(env, object, "permissions")) {
166 NAPI_BT_CALL_RETURN(NapiParseObjectGattPermissions(env, object, "permissions", permissions));
167 }
168
169 outDescriptor.serviceUuid = UUID::FromString(serviceUuid);
170 outDescriptor.characteristicUuid = UUID::FromString(characterUuid);
171 outDescriptor.descriptorUuid = UUID::FromString(descriptorUuid);
172 outDescriptor.descriptorValue = std::move(descriptorValue);
173 outDescriptor.permissions = ConvertGattPermissions(permissions);
174 return napi_ok;
175 }
176
NapiParseNotifyCharacteristic(napi_env env,napi_value object,NapiNotifyCharacteristic & outCharacter)177 napi_status NapiParseNotifyCharacteristic(napi_env env, napi_value object, NapiNotifyCharacteristic &outCharacter)
178 {
179 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
180 "characteristicValue", "confirm"}));
181
182 std::string serviceUuid {};
183 std::string characterUuid {};
184 std::vector<uint8_t> characterValue {};
185 bool confirm = false;
186 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
187 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
188 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
189 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "characteristicValue", characterValue));
190 NAPI_BT_CALL_RETURN(NapiParseObjectBoolean(env, object, "confirm", confirm));
191
192 outCharacter.serviceUuid = UUID::FromString(serviceUuid);
193 outCharacter.characterUuid = UUID::FromString(characterUuid);
194 outCharacter.characterValue = std::move(characterValue);
195 outCharacter.confirm = confirm;
196 return napi_ok;
197 }
198
NapiParseGattsServerResponse(napi_env env,napi_value object,NapiGattsServerResponse & rsp)199 napi_status NapiParseGattsServerResponse(napi_env env, napi_value object, NapiGattsServerResponse &rsp)
200 {
201 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"deviceId", "transId", "status", "offset",
202 "value"}));
203
204 std::string deviceId {};
205 int transId = 0;
206 int status = 0;
207 int offset = 0;
208 std::vector<uint8_t> value {};
209 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
210 NAPI_BT_CALL_RETURN(NapiParseObjectBdAddr(env, object, "deviceId", deviceId));
211 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "transId", transId));
212 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "status", status));
213 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "offset", offset));
214 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "value", value));
215
216 rsp.deviceId = deviceId;
217 rsp.transId = transId;
218 rsp.status = status;
219 rsp.offset = offset;
220 rsp.value = std::move(value);
221 return napi_ok;
222 }
223
NapiParseObjectGattPermissions(napi_env env,napi_value object,const char * name,NapiGattPermission & outPermissions)224 napi_status NapiParseObjectGattPermissions(napi_env env, napi_value object, const char *name,
225 NapiGattPermission &outPermissions)
226 {
227 napi_value permissionObject;
228 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
229 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, permissionObject));
230 // Parse permission object
231 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, permissionObject, {"readable", "writeable",
232 "readEncrypted", "writeEncrypted"}));
233
234 bool isExist;
235 NapiGattPermission permissions {};
236 NAPI_BT_CALL_RETURN(
237 NapiParseObjectBooleanOptional(env, permissionObject, "readable", permissions.readable, isExist));
238 NAPI_BT_CALL_RETURN(
239 NapiParseObjectBooleanOptional(env, permissionObject, "writeable", permissions.writeable, isExist));
240 NAPI_BT_CALL_RETURN(
241 NapiParseObjectBooleanOptional(env, permissionObject, "readEncrypted", permissions.readEncrypted, isExist));
242 NAPI_BT_CALL_RETURN(
243 NapiParseObjectBooleanOptional(env, permissionObject, "writeEncrypted", permissions.writeEncrypted, isExist));
244 outPermissions = permissions;
245 return napi_ok;
246 }
247
NapiParseObjectGattProperties(napi_env env,napi_value object,const char * name,NapiGattProperties & outProperties)248 napi_status NapiParseObjectGattProperties(napi_env env, napi_value object, const char *name,
249 NapiGattProperties &outProperties)
250 {
251 napi_value propertiesObject;
252 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
253 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, propertiesObject));
254 // Parse properties object
255 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, propertiesObject, {"write", "writeNoResponse",
256 "read", "notify", "indicate"}));
257
258 bool isExist;
259 NapiGattProperties properties {};
260 NAPI_BT_CALL_RETURN(
261 NapiParseObjectBooleanOptional(env, propertiesObject, "write", properties.write, isExist));
262 NAPI_BT_CALL_RETURN(
263 NapiParseObjectBooleanOptional(env, propertiesObject, "writeNoResponse", properties.writeNoResponse, isExist));
264 NAPI_BT_CALL_RETURN(
265 NapiParseObjectBooleanOptional(env, propertiesObject, "read", properties.read, isExist));
266 NAPI_BT_CALL_RETURN(
267 NapiParseObjectBooleanOptional(env, propertiesObject, "notify", properties.notify, isExist));
268 NAPI_BT_CALL_RETURN(
269 NapiParseObjectBooleanOptional(env, propertiesObject, "indicate", properties.indicate, isExist));
270 outProperties = properties;
271 return napi_ok;
272 }
273
NapiParseBoolean(napi_env env,napi_value value,bool & outBoolean)274 napi_status NapiParseBoolean(napi_env env, napi_value value, bool &outBoolean)
275 {
276 bool boolean = false;
277 NAPI_BT_CALL_RETURN(NapiIsBoolean(env, value));
278 NAPI_BT_CALL_RETURN(napi_get_value_bool(env, value, &boolean));
279 outBoolean = boolean;
280 return napi_ok;
281 }
282
NapiParseInt32(napi_env env,napi_value value,int32_t & outNum)283 napi_status NapiParseInt32(napi_env env, napi_value value, int32_t &outNum)
284 {
285 int32_t num = 0;
286 NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
287 NAPI_BT_CALL_RETURN(napi_get_value_int32(env, value, &num));
288 outNum = num;
289 return napi_ok;
290 }
291
NapiParseUint32(napi_env env,napi_value value,uint32_t & outNum)292 napi_status NapiParseUint32(napi_env env, napi_value value, uint32_t &outNum)
293 {
294 uint32_t num = 0;
295 NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
296 NAPI_BT_CALL_RETURN(napi_get_value_uint32(env, value, &num));
297 outNum = num;
298 return napi_ok;
299 }
300
NapiParseString(napi_env env,napi_value value,std::string & outStr)301 napi_status NapiParseString(napi_env env, napi_value value, std::string &outStr)
302 {
303 std::string str {};
304 NAPI_BT_CALL_RETURN(NapiIsString(env, value));
305 NAPI_BT_RETURN_IF(!ParseString(env, str, value), "parse string failed", napi_invalid_arg);
306 outStr = std::move(str);
307 return napi_ok;
308 }
309
NapiParseBdAddr(napi_env env,napi_value value,std::string & outAddr)310 napi_status NapiParseBdAddr(napi_env env, napi_value value, std::string &outAddr)
311 {
312 std::string bdaddr {};
313 NAPI_BT_CALL_RETURN(NapiParseString(env, value, bdaddr));
314 NAPI_BT_RETURN_IF(!IsValidAddress(bdaddr), "Invalid bdaddr", napi_invalid_arg);
315 outAddr = std::move(bdaddr);
316 return napi_ok;
317 }
318
NapiParseUuid(napi_env env,napi_value value,std::string & outUuid)319 napi_status NapiParseUuid(napi_env env, napi_value value, std::string &outUuid)
320 {
321 std::string uuid {};
322 NAPI_BT_CALL_RETURN(NapiParseString(env, value, uuid));
323 NAPI_BT_RETURN_IF(!IsValidUuid(uuid), "Invalid uuid", napi_invalid_arg);
324 outUuid = std::move(uuid);
325 return napi_ok;
326 }
327
NapiParseArrayBuffer(napi_env env,napi_value value,std::vector<uint8_t> & outVec)328 napi_status NapiParseArrayBuffer(napi_env env, napi_value value, std::vector<uint8_t> &outVec)
329 {
330 uint8_t *data = nullptr;
331 size_t size = 0;
332 NAPI_BT_CALL_RETURN(NapiIsArrayBuffer(env, value));
333 bool isSuccess = ParseArrayBuffer(env, &data, size, value);
334 if (!isSuccess) {
335 HILOGE("Parse arraybuffer failed");
336 return napi_invalid_arg;
337 }
338 std::vector<uint8_t> vec(data, data + size);
339 outVec = std::move(vec);
340 return napi_ok;
341 }
342
NapiParseGattWriteType(napi_env env,napi_value value,int & outWriteType)343 napi_status NapiParseGattWriteType(napi_env env, napi_value value, int &outWriteType)
344 {
345 int writeType = -1;
346 NAPI_BT_CALL_RETURN(NapiParseInt32(env, value, writeType));
347 if (writeType == static_cast<int>(NapiGattWriteType::WRITE)) {
348 HILOGI("gattWriteType: WRITE");
349 outWriteType = GattCharacteristic::WriteType::DEFAULT;
350 } else if (writeType == static_cast<int>(NapiGattWriteType::WRITE_NO_RESPONSE)) {
351 HILOGI("gattWriteType: WRITE_NO_RESPONSE");
352 outWriteType = GattCharacteristic::WriteType::NO_RESPONSE;
353 } else {
354 HILOGE("Invalid gattWriteType: %{public}d", writeType);
355 return napi_invalid_arg;
356 }
357 return napi_ok;
358 }
359
NapiParseAsyncCallback(napi_env env,napi_callback_info info)360 std::shared_ptr<NapiAsyncCallback> NapiParseAsyncCallback(napi_env env, napi_callback_info info)
361 {
362 size_t argc = ARGS_SIZE_FOUR;
363 napi_value argv[ARGS_SIZE_FOUR] = {nullptr};
364 auto status = napi_get_cb_info(env, info, &argc, argv, nullptr, NULL);
365 if (status != napi_ok) {
366 HILOGE("napi_get_cb_info failed");
367 return nullptr;
368 }
369 if (argc > ARGS_SIZE_FOUR) {
370 HILOGE("size of parameters is larger than ARGS_SIZE_FOUR");
371 return nullptr;
372 }
373
374 // "argc - 1" is AsyncCallback parameter's index
375 auto asyncCallback = std::make_shared<NapiAsyncCallback>();
376 asyncCallback->env = env;
377 if (argc > 0 && NapiIsFunction(env, argv[argc - 1]) == napi_ok) {
378 HILOGD("callback mode");
379 asyncCallback->callback = std::make_shared<NapiCallback>(env, argv[argc - 1]);
380 } else {
381 HILOGD("promise mode");
382 asyncCallback->promise = std::make_shared<NapiPromise>(env);
383 }
384 return asyncCallback;
385 }
386
NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)387 static napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty,
388 bool &outExist)
389 {
390 bool exist = false;
391 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
392 NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &exist));
393 if (exist) {
394 napi_value property;
395 NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
396 outProperty = property;
397 }
398 outExist = exist;
399 return napi_ok;
400 }
NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty)401 napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty)
402 {
403 bool exist = false;
404 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, outProperty, exist));
405 NAPI_BT_RETURN_IF(!exist, "no needed property", napi_invalid_arg);
406 return napi_ok;
407 }
NapiGetObjectPropertyOptional(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)408 napi_status NapiGetObjectPropertyOptional(napi_env env, napi_value object, const char *name, napi_value &outProperty,
409 bool &outExist)
410 {
411 return NapiGetObjectProperty(env, object, name, outProperty, outExist);
412 }
413
NapiParseObjectBoolean(napi_env env,napi_value object,const char * name,bool & outBoolean)414 napi_status NapiParseObjectBoolean(napi_env env, napi_value object, const char *name, bool &outBoolean)
415 {
416 napi_value property;
417 bool boolean = true;
418 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
419 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
420 NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean));
421 outBoolean = boolean;
422 return napi_ok;
423 }
424
NapiParseObjectUuid(napi_env env,napi_value object,const char * name,std::string & outUuid)425 napi_status NapiParseObjectUuid(napi_env env, napi_value object, const char *name, std::string &outUuid)
426 {
427 napi_value property;
428 std::string uuid {};
429 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
430 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
431 NAPI_BT_CALL_RETURN(NapiParseUuid(env, property, uuid));
432 outUuid = std::move(uuid);
433 return napi_ok;
434 }
435
NapiParseObjectArrayBuffer(napi_env env,napi_value object,const char * name,std::vector<uint8_t> & outVec)436 napi_status NapiParseObjectArrayBuffer(napi_env env, napi_value object, const char *name, std::vector<uint8_t> &outVec)
437 {
438 napi_value property;
439 std::vector<uint8_t> vec {};
440 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
441 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
442 NAPI_BT_CALL_RETURN(NapiParseArrayBuffer(env, property, vec));
443 outVec = std::move(vec);
444 return napi_ok;
445 }
446
NapiParseObjectBdAddr(napi_env env,napi_value object,const char * name,std::string & outAddr)447 napi_status NapiParseObjectBdAddr(napi_env env, napi_value object, const char *name, std::string &outAddr)
448 {
449 napi_value property;
450 std::string bdaddr {};
451 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
452 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
453 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, property, bdaddr));
454 outAddr = std::move(bdaddr);
455 return napi_ok;
456 }
457
NapiParseObjectInt32(napi_env env,napi_value object,const char * name,int32_t & outNum)458 napi_status NapiParseObjectInt32(napi_env env, napi_value object, const char *name, int32_t &outNum)
459 {
460 napi_value property;
461 int32_t num = 0;
462 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
463 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
464 NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num));
465 outNum = num;
466 return napi_ok;
467 }
468
NapiParseObjectUint32(napi_env env,napi_value object,const char * name,uint32_t & outNum)469 napi_status NapiParseObjectUint32(napi_env env, napi_value object, const char *name, uint32_t &outNum)
470 {
471 napi_value property;
472 uint32_t num = 0;
473 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
474 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
475 NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num));
476 outNum = num;
477 return napi_ok;
478 }
479
NapiParseObjectBooleanOptional(napi_env env,napi_value object,const char * name,bool & outBoolean,bool & outExist)480 napi_status NapiParseObjectBooleanOptional(napi_env env, napi_value object, const char *name, bool &outBoolean,
481 bool &outExist)
482 {
483 napi_value property;
484 bool exist = false;
485 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
486 NAPI_BT_CALL_RETURN(NapiGetObjectPropertyOptional(env, object, name, property, exist));
487 if (exist) {
488 bool boolean = true;
489 NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean));
490 outBoolean = boolean;
491 }
492 outExist = exist;
493 return napi_ok;
494 }
NapiParseObjectInt32Optional(napi_env env,napi_value object,const char * name,int32_t & outNum,bool & outExist)495 napi_status NapiParseObjectInt32Optional(napi_env env, napi_value object, const char *name, int32_t &outNum,
496 bool &outExist)
497 {
498 napi_value property;
499 bool exist = false;
500 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
501 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist));
502 if (exist) {
503 int32_t num = 0;
504 NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num));
505 outNum = num;
506 }
507 outExist = exist;
508 return napi_ok;
509 }
NapiParseObjectUint32Optional(napi_env env,napi_value object,const char * name,uint32_t & outNum,bool & outExist)510 napi_status NapiParseObjectUint32Optional(napi_env env, napi_value object, const char *name, uint32_t &outNum,
511 bool &outExist)
512 {
513 napi_value property;
514 bool exist = false;
515 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
516 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist));
517 if (exist) {
518 uint32_t num = 0;
519 NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num));
520 outNum = num;
521 }
522 outExist = exist;
523 return napi_ok;
524 }
525
526 // Parse params template, used for NapiParseArray
527 template <typename T>
NapiParseObject(napi_env env,napi_value object,T & outObj)528 napi_status NapiParseObject(napi_env env, napi_value object, T &outObj)
529 {
530 HILOGE("Unimpleted type");
531 return napi_invalid_arg;
532 }
533
534 template <>
NapiParseObject(napi_env env,napi_value object,std::string & outObj)535 napi_status NapiParseObject<std::string>(napi_env env, napi_value object, std::string &outObj)
536 {
537 return NapiParseString(env, object, outObj);
538 }
539
540 template <>
NapiParseObject(napi_env env,napi_value object,UUID & outObj)541 napi_status NapiParseObject<UUID>(napi_env env, napi_value object, UUID &outObj)
542 {
543 std::string uuid {};
544 NAPI_BT_CALL_RETURN(NapiParseUuid(env, object, uuid));
545 outObj = UUID::FromString(uuid);
546 return napi_ok;
547 }
548
549 template <>
NapiParseObject(napi_env env,napi_value object,NapiAdvManufactureData & outObj)550 napi_status NapiParseObject<NapiAdvManufactureData>(napi_env env, napi_value object, NapiAdvManufactureData &outObj)
551 {
552 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"manufactureId", "manufactureValue"}));
553 uint32_t num = 0;
554 std::vector<uint8_t> vec {};
555 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
556 NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, object, "manufactureId", num));
557 NAPI_BT_RETURN_IF(num > 0xFFFF, "Invalid manufactureId", napi_invalid_arg);
558 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "manufactureValue", vec));
559
560 outObj.id = static_cast<uint16_t>(num);
561 outObj.value = std::string(vec.begin(), vec.end());
562 return napi_ok;
563 }
564
565 template <>
NapiParseObject(napi_env env,napi_value object,NapiAdvServiceData & outObj)566 napi_status NapiParseObject<NapiAdvServiceData>(napi_env env, napi_value object, NapiAdvServiceData &outObj)
567 {
568 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "serviceValue"}));
569 std::string uuid {};
570 std::vector<uint8_t> vec {};
571 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
572 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", uuid));
573 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "serviceValue", vec));
574
575 outObj.uuid = std::move(uuid);
576 outObj.value = std::move(vec);
577 return napi_ok;
578 }
579
580 template <>
NapiParseObject(napi_env env,napi_value object,NapiGattService & outObj)581 napi_status NapiParseObject<NapiGattService>(napi_env env, napi_value object, NapiGattService &outObj)
582 {
583 return NapiParseGattService(env, object, outObj);
584 }
585
586 template <>
NapiParseObject(napi_env env,napi_value object,NapiBleCharacteristic & outObj)587 napi_status NapiParseObject<NapiBleCharacteristic>(napi_env env, napi_value object, NapiBleCharacteristic &outObj)
588 {
589 return NapiParseGattCharacteristic(env, object, outObj);
590 }
591
592 template <>
NapiParseObject(napi_env env,napi_value object,NapiBleDescriptor & outObj)593 napi_status NapiParseObject<NapiBleDescriptor>(napi_env env, napi_value object, NapiBleDescriptor &outObj)
594 {
595 return NapiParseGattDescriptor(env, object, outObj);
596 }
597
598 template <typename T>
NapiParseArray(napi_env env,napi_value array,std::vector<T> & outVec)599 napi_status NapiParseArray(napi_env env, napi_value array, std::vector<T> &outVec)
600 {
601 std::vector<T> vec {};
602
603 NAPI_BT_CALL_RETURN(NapiIsArray(env, array));
604 uint32_t length = 0;
605 NAPI_BT_CALL_RETURN(napi_get_array_length(env, array, &length));
606 for (uint32_t i = 0; i < length; ++i) {
607 napi_value element;
608 NAPI_BT_CALL_RETURN(napi_get_element(env, array, i, &element));
609 T object;
610 NAPI_BT_CALL_RETURN(NapiParseObject(env, element, object));
611 vec.push_back(std::move(object));
612 }
613 outVec = std::move(vec);
614 return napi_ok;
615 }
616 // // Declaration, ohters will undefined synbol
617 template napi_status NapiParseArray<NapiBleDescriptor>(napi_env env, napi_value array,
618 std::vector<NapiBleDescriptor> &outVec);
619 template napi_status NapiParseArray<NapiBleCharacteristic>(napi_env env, napi_value array,
620 std::vector<NapiBleCharacteristic> &outVec);
621 template napi_status NapiParseArray<NapiGattService>(napi_env env, napi_value array,
622 std::vector<NapiGattService> &outVec);
623 template napi_status NapiParseArray<NapiAdvServiceData>(napi_env env, napi_value array,
624 std::vector<NapiAdvServiceData> &outVec);
625 template napi_status NapiParseArray<NapiAdvManufactureData>(napi_env env, napi_value array,
626 std::vector<NapiAdvManufactureData> &outVec);
627 template napi_status NapiParseArray<UUID>(napi_env env, napi_value array,
628 std::vector<UUID> &outVec);
629 template napi_status NapiParseArray<std::string>(napi_env env, napi_value array,
630 std::vector<std::string> &outVec);
631
632
633 template <typename T>
NapiParseObjectArray(napi_env env,napi_value object,const char * name,std::vector<T> & outVec)634 napi_status NapiParseObjectArray(napi_env env, napi_value object, const char *name, std::vector<T> &outVec)
635 {
636 napi_value property;
637 std::vector<T> vec {};
638 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
639 NAPI_BT_CALL_RETURN(NapiParseArray(env, property, vec));
640 outVec = std::move(vec);
641 return napi_ok;
642 }
643 // Declaration, ohters will undefined synbol
644 template napi_status NapiParseObjectArray<NapiBleDescriptor>(napi_env env, napi_value object, const char *name,
645 std::vector<NapiBleDescriptor> &outVec);
646 template napi_status NapiParseObjectArray<NapiBleCharacteristic>(napi_env env, napi_value object, const char *name,
647 std::vector<NapiBleCharacteristic> &outVec);
648 template napi_status NapiParseObjectArray<NapiGattService>(napi_env env, napi_value object, const char *name,
649 std::vector<NapiGattService> &outVec);
650 template napi_status NapiParseObjectArray<NapiAdvServiceData>(napi_env env, napi_value object, const char *name,
651 std::vector<NapiAdvServiceData> &outVec);
652 template napi_status NapiParseObjectArray<NapiAdvManufactureData>(napi_env env, napi_value object, const char *name,
653 std::vector<NapiAdvManufactureData> &outVec);
654 template napi_status NapiParseObjectArray<UUID>(napi_env env, napi_value object, const char *name,
655 std::vector<UUID> &outVec);
656 template napi_status NapiParseObjectArray<std::string>(napi_env env, napi_value object, const char *name,
657 std::vector<std::string> &outVec);
658 } // namespace Bluetooth
659 } // namespace OHOS
660