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