• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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 
NapiParseStringArray(napi_env env,napi_value value,std::vector<std::string> & outStrVec)310 napi_status NapiParseStringArray(napi_env env, napi_value value, std::vector<std::string> &outStrVec)
311 {
312     NAPI_BT_CALL_RETURN(NapiIsArray(env, value));
313     uint32_t length = 0;
314     std::string param {};
315     std::vector<std::string> strVec {};
316     napi_get_array_length(env, value, &length);
317     for (size_t i = 0; i < length; i++) {
318         napi_value result;
319         napi_get_element(env, value, i, &result);
320         NAPI_BT_CALL_RETURN(NapiParseString(env, result, param));
321         strVec.push_back(param);
322     }
323     outStrVec = std::move(strVec);
324     return napi_ok;
325 }
326 
NapiParseBdAddr(napi_env env,napi_value value,std::string & outAddr)327 napi_status NapiParseBdAddr(napi_env env, napi_value value, std::string &outAddr)
328 {
329     std::string bdaddr {};
330     NAPI_BT_CALL_RETURN(NapiParseString(env, value, bdaddr));
331     NAPI_BT_RETURN_IF(!IsValidAddress(bdaddr), "Invalid bdaddr", napi_invalid_arg);
332     outAddr = std::move(bdaddr);
333     return napi_ok;
334 }
335 
NapiParseUuid(napi_env env,napi_value value,std::string & outUuid)336 napi_status NapiParseUuid(napi_env env, napi_value value, std::string &outUuid)
337 {
338     std::string uuid {};
339     NAPI_BT_CALL_RETURN(NapiParseString(env, value, uuid));
340     NAPI_BT_RETURN_IF(!IsValidUuid(uuid), "Invalid uuid", napi_invalid_arg);
341     outUuid = std::move(uuid);
342     return napi_ok;
343 }
344 
NapiParseArrayBuffer(napi_env env,napi_value value,std::vector<uint8_t> & outVec)345 napi_status NapiParseArrayBuffer(napi_env env, napi_value value, std::vector<uint8_t> &outVec)
346 {
347     uint8_t *data = nullptr;
348     size_t size = 0;
349     NAPI_BT_CALL_RETURN(NapiIsArrayBuffer(env, value));
350     bool isSuccess = ParseArrayBuffer(env, &data, size, value);
351     if (!isSuccess) {
352         HILOGE("Parse arraybuffer failed");
353         return napi_invalid_arg;
354     }
355     std::vector<uint8_t> vec(data, data + size);
356     outVec = std::move(vec);
357     return napi_ok;
358 }
359 
NapiParseGattWriteType(napi_env env,napi_value value,int & outWriteType)360 napi_status NapiParseGattWriteType(napi_env env, napi_value value, int &outWriteType)
361 {
362     int writeType = -1;
363     NAPI_BT_CALL_RETURN(NapiParseInt32(env, value, writeType));
364     if (writeType == static_cast<int>(NapiGattWriteType::WRITE)) {
365         HILOGI("gattWriteType: WRITE");
366         outWriteType = GattCharacteristic::WriteType::DEFAULT;
367     } else if (writeType == static_cast<int>(NapiGattWriteType::WRITE_NO_RESPONSE)) {
368         HILOGI("gattWriteType: WRITE_NO_RESPONSE");
369         outWriteType = GattCharacteristic::WriteType::NO_RESPONSE;
370     } else {
371         HILOGE("Invalid gattWriteType: %{public}d", writeType);
372         return napi_invalid_arg;
373     }
374     return napi_ok;
375 }
376 
NapiParseAsyncCallback(napi_env env,napi_callback_info info)377 std::shared_ptr<NapiAsyncCallback> NapiParseAsyncCallback(napi_env env, napi_callback_info info)
378 {
379     size_t argc = ARGS_SIZE_FOUR;
380     napi_value argv[ARGS_SIZE_FOUR] = {nullptr};
381     auto status = napi_get_cb_info(env, info, &argc, argv, nullptr, NULL);
382     if (status != napi_ok) {
383         HILOGE("napi_get_cb_info failed");
384         return nullptr;
385     }
386     if (argc > ARGS_SIZE_FOUR) {
387         HILOGE("size of parameters is larger than ARGS_SIZE_FOUR");
388         return nullptr;
389     }
390 
391     // "argc - 1" is AsyncCallback parameter's index
392     auto asyncCallback = std::make_shared<NapiAsyncCallback>();
393     asyncCallback->env = env;
394     if (argc > 0 && NapiIsFunction(env, argv[argc - 1]) == napi_ok) {
395         HILOGD("callback mode");
396         asyncCallback->callback = std::make_shared<NapiCallback>(env, argv[argc - 1]);
397     } else {
398         HILOGD("promise mode");
399         asyncCallback->promise = std::make_shared<NapiPromise>(env);
400     }
401     return asyncCallback;
402 }
403 
NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)404 static napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty,
405     bool &outExist)
406 {
407     bool exist = false;
408     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
409     NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &exist));
410     if (exist) {
411         napi_value property;
412         NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
413         outProperty = property;
414     }
415     outExist = exist;
416     return napi_ok;
417 }
NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty)418 napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty)
419 {
420     bool exist = false;
421     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, outProperty, exist));
422     NAPI_BT_RETURN_IF(!exist, "no needed property", napi_invalid_arg);
423     return napi_ok;
424 }
NapiGetObjectPropertyOptional(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)425 napi_status NapiGetObjectPropertyOptional(napi_env env, napi_value object, const char *name, napi_value &outProperty,
426     bool &outExist)
427 {
428     return NapiGetObjectProperty(env, object, name, outProperty, outExist);
429 }
430 
NapiParseObjectBoolean(napi_env env,napi_value object,const char * name,bool & outBoolean)431 napi_status NapiParseObjectBoolean(napi_env env, napi_value object, const char *name, bool &outBoolean)
432 {
433     napi_value property;
434     bool boolean = true;
435     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
436     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
437     NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean));
438     outBoolean = boolean;
439     return napi_ok;
440 }
441 
NapiParseObjectUuid(napi_env env,napi_value object,const char * name,std::string & outUuid)442 napi_status NapiParseObjectUuid(napi_env env, napi_value object, const char *name, std::string &outUuid)
443 {
444     napi_value property;
445     std::string uuid {};
446     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
447     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
448     NAPI_BT_CALL_RETURN(NapiParseUuid(env, property, uuid));
449     outUuid = std::move(uuid);
450     return napi_ok;
451 }
452 
NapiParseObjectArrayBuffer(napi_env env,napi_value object,const char * name,std::vector<uint8_t> & outVec)453 napi_status NapiParseObjectArrayBuffer(napi_env env, napi_value object, const char *name, std::vector<uint8_t> &outVec)
454 {
455     napi_value property;
456     std::vector<uint8_t> vec {};
457     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
458     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
459     NAPI_BT_CALL_RETURN(NapiParseArrayBuffer(env, property, vec));
460     outVec = std::move(vec);
461     return napi_ok;
462 }
463 
NapiParseObjectBdAddr(napi_env env,napi_value object,const char * name,std::string & outAddr)464 napi_status NapiParseObjectBdAddr(napi_env env, napi_value object, const char *name, std::string &outAddr)
465 {
466     napi_value property;
467     std::string bdaddr {};
468     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
469     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
470     NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, property, bdaddr));
471     outAddr = std::move(bdaddr);
472     return napi_ok;
473 }
474 
NapiParseObjectInt32(napi_env env,napi_value object,const char * name,int32_t & outNum)475 napi_status NapiParseObjectInt32(napi_env env, napi_value object, const char *name, int32_t &outNum)
476 {
477     napi_value property;
478     int32_t num = 0;
479     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
480     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
481     NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num));
482     outNum = num;
483     return napi_ok;
484 }
485 
NapiParseObjectUint32(napi_env env,napi_value object,const char * name,uint32_t & outNum)486 napi_status NapiParseObjectUint32(napi_env env, napi_value object, const char *name, uint32_t &outNum)
487 {
488     napi_value property;
489     uint32_t num = 0;
490     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
491     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
492     NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num));
493     outNum = num;
494     return napi_ok;
495 }
496 
NapiParseObjectBooleanOptional(napi_env env,napi_value object,const char * name,bool & outBoolean,bool & outExist)497 napi_status NapiParseObjectBooleanOptional(napi_env env, napi_value object, const char *name, bool &outBoolean,
498     bool &outExist)
499 {
500     napi_value property;
501     bool exist = false;
502     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
503     NAPI_BT_CALL_RETURN(NapiGetObjectPropertyOptional(env, object, name, property, exist));
504     if (exist) {
505         bool boolean = true;
506         NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean));
507         outBoolean = boolean;
508     }
509     outExist = exist;
510     return napi_ok;
511 }
NapiParseObjectInt32Optional(napi_env env,napi_value object,const char * name,int32_t & outNum,bool & outExist)512 napi_status NapiParseObjectInt32Optional(napi_env env, napi_value object, const char *name, int32_t &outNum,
513     bool &outExist)
514 {
515     napi_value property;
516     bool exist = false;
517     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
518     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist));
519     if (exist) {
520         int32_t num = 0;
521         NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num));
522         outNum = num;
523     }
524     outExist = exist;
525     return napi_ok;
526 }
NapiParseObjectUint32Optional(napi_env env,napi_value object,const char * name,uint32_t & outNum,bool & outExist)527 napi_status NapiParseObjectUint32Optional(napi_env env, napi_value object, const char *name, uint32_t &outNum,
528     bool &outExist)
529 {
530     napi_value property;
531     bool exist = false;
532     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
533     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist));
534     if (exist) {
535         uint32_t num = 0;
536         NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num));
537         outNum = num;
538     }
539     outExist = exist;
540     return napi_ok;
541 }
542 
543 // Parse params template, used for NapiParseArray
544 template <typename T>
NapiParseObject(napi_env env,napi_value object,T & outObj)545 napi_status NapiParseObject(napi_env env, napi_value object, T &outObj)
546 {
547     HILOGE("Unimpleted type");
548     return napi_invalid_arg;
549 }
550 
551 template <>
NapiParseObject(napi_env env,napi_value object,std::string & outObj)552 napi_status NapiParseObject<std::string>(napi_env env, napi_value object, std::string &outObj)
553 {
554     return NapiParseString(env, object, outObj);
555 }
556 
557 template <>
NapiParseObject(napi_env env,napi_value object,UUID & outObj)558 napi_status NapiParseObject<UUID>(napi_env env, napi_value object, UUID &outObj)
559 {
560     std::string uuid {};
561     NAPI_BT_CALL_RETURN(NapiParseUuid(env, object, uuid));
562     outObj = UUID::FromString(uuid);
563     return napi_ok;
564 }
565 
566 template <>
NapiParseObject(napi_env env,napi_value object,NapiAdvManufactureData & outObj)567 napi_status NapiParseObject<NapiAdvManufactureData>(napi_env env, napi_value object, NapiAdvManufactureData &outObj)
568 {
569     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"manufactureId", "manufactureValue"}));
570     uint32_t num = 0;
571     std::vector<uint8_t> vec {};
572     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
573     NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, object, "manufactureId", num));
574     NAPI_BT_RETURN_IF(num > 0xFFFF, "Invalid manufactureId", napi_invalid_arg);
575     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "manufactureValue", vec));
576 
577     outObj.id = static_cast<uint16_t>(num);
578     outObj.value = std::string(vec.begin(), vec.end());
579     return napi_ok;
580 }
581 
582 template <>
NapiParseObject(napi_env env,napi_value object,NapiAdvServiceData & outObj)583 napi_status NapiParseObject<NapiAdvServiceData>(napi_env env, napi_value object, NapiAdvServiceData &outObj)
584 {
585     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "serviceValue"}));
586     std::string uuid {};
587     std::vector<uint8_t> vec {};
588     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
589     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", uuid));
590     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "serviceValue", vec));
591 
592     outObj.uuid = std::move(uuid);
593     outObj.value = std::move(vec);
594     return napi_ok;
595 }
596 
597 template <>
NapiParseObject(napi_env env,napi_value object,NapiGattService & outObj)598 napi_status NapiParseObject<NapiGattService>(napi_env env, napi_value object, NapiGattService &outObj)
599 {
600     return NapiParseGattService(env, object, outObj);
601 }
602 
603 template <>
NapiParseObject(napi_env env,napi_value object,NapiBleCharacteristic & outObj)604 napi_status NapiParseObject<NapiBleCharacteristic>(napi_env env, napi_value object, NapiBleCharacteristic &outObj)
605 {
606     return NapiParseGattCharacteristic(env, object, outObj);
607 }
608 
609 template <>
NapiParseObject(napi_env env,napi_value object,NapiBleDescriptor & outObj)610 napi_status NapiParseObject<NapiBleDescriptor>(napi_env env, napi_value object, NapiBleDescriptor &outObj)
611 {
612     return NapiParseGattDescriptor(env, object, outObj);
613 }
614 
615 template <typename T>
NapiParseArray(napi_env env,napi_value array,std::vector<T> & outVec)616 napi_status NapiParseArray(napi_env env, napi_value array, std::vector<T> &outVec)
617 {
618     std::vector<T> vec {};
619 
620     NAPI_BT_CALL_RETURN(NapiIsArray(env, array));
621     uint32_t length = 0;
622     NAPI_BT_CALL_RETURN(napi_get_array_length(env, array, &length));
623     for (uint32_t i = 0; i < length; ++i) {
624         napi_value element;
625         NAPI_BT_CALL_RETURN(napi_get_element(env, array, i, &element));
626         T object;
627         NAPI_BT_CALL_RETURN(NapiParseObject(env, element, object));
628         vec.push_back(std::move(object));
629     }
630     outVec = std::move(vec);
631     return napi_ok;
632 }
633 // // Declaration, ohters will undefined synbol
634 template napi_status NapiParseArray<NapiBleDescriptor>(napi_env env, napi_value array,
635     std::vector<NapiBleDescriptor> &outVec);
636 template napi_status NapiParseArray<NapiBleCharacteristic>(napi_env env, napi_value array,
637     std::vector<NapiBleCharacteristic> &outVec);
638 template napi_status NapiParseArray<NapiGattService>(napi_env env, napi_value array,
639     std::vector<NapiGattService> &outVec);
640 template napi_status NapiParseArray<NapiAdvServiceData>(napi_env env, napi_value array,
641     std::vector<NapiAdvServiceData> &outVec);
642 template napi_status NapiParseArray<NapiAdvManufactureData>(napi_env env, napi_value array,
643     std::vector<NapiAdvManufactureData> &outVec);
644 template napi_status NapiParseArray<UUID>(napi_env env, napi_value array,
645     std::vector<UUID> &outVec);
646 template napi_status NapiParseArray<std::string>(napi_env env, napi_value array,
647     std::vector<std::string> &outVec);
648 
649 
650 template <typename T>
NapiParseObjectArray(napi_env env,napi_value object,const char * name,std::vector<T> & outVec)651 napi_status NapiParseObjectArray(napi_env env, napi_value object, const char *name, std::vector<T> &outVec)
652 {
653     napi_value property;
654     std::vector<T> vec {};
655     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
656     NAPI_BT_CALL_RETURN(NapiParseArray(env, property, vec));
657     outVec = std::move(vec);
658     return napi_ok;
659 }
660 // Declaration, ohters will undefined synbol
661 template napi_status NapiParseObjectArray<NapiBleDescriptor>(napi_env env, napi_value object, const char *name,
662     std::vector<NapiBleDescriptor> &outVec);
663 template napi_status NapiParseObjectArray<NapiBleCharacteristic>(napi_env env, napi_value object, const char *name,
664     std::vector<NapiBleCharacteristic> &outVec);
665 template napi_status NapiParseObjectArray<NapiGattService>(napi_env env, napi_value object, const char *name,
666     std::vector<NapiGattService> &outVec);
667 template napi_status NapiParseObjectArray<NapiAdvServiceData>(napi_env env, napi_value object, const char *name,
668     std::vector<NapiAdvServiceData> &outVec);
669 template napi_status NapiParseObjectArray<NapiAdvManufactureData>(napi_env env, napi_value object, const char *name,
670     std::vector<NapiAdvManufactureData> &outVec);
671 template napi_status NapiParseObjectArray<UUID>(napi_env env, napi_value object, const char *name,
672     std::vector<UUID> &outVec);
673 template napi_status NapiParseObjectArray<std::string>(napi_env env, napi_value object, const char *name,
674     std::vector<std::string> &outVec);
675 }  // namespace Bluetooth
676 }  // namespace OHOS
677