• 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 #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 #include <cinttypes>
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", "characteristicValueHandle", "permissions"}));
123 
124     std::string serviceUuid {};
125     std::string characterUuid {};
126     std::vector<uint8_t> characterValue {};
127     std::vector<NapiBleDescriptor> descriptors {};
128     uint32_t characteristicValueHandle = 0;
129     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
130     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
131     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
132     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "characteristicValue", characterValue));
133     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "descriptors", descriptors));
134 
135     NapiGattProperties properties = DEFAULT_GATT_PROPERTIES;
136     if (NapiIsObjectPropertyExist(env, object, "properties"))  {
137         NAPI_BT_CALL_RETURN(NapiParseObjectGattProperties(env, object, "properties", properties));
138     }
139     if (NapiIsObjectPropertyExist(env, object, "characteristicValueHandle")) {
140         NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, object, "characteristicValueHandle", characteristicValueHandle));
141         NAPI_BT_RETURN_IF(characteristicValueHandle > 0xFFFF, "Invalid characteristicValueHandle", napi_invalid_arg);
142     }
143     NapiGattPermission permissions = DEFAULT_GATT_PERMISSIONS;
144     if (NapiIsObjectPropertyExist(env, object, "permissions")) {
145         NAPI_BT_CALL_RETURN(NapiParseObjectGattPermissions(env, object, "permissions", permissions));
146     }
147 
148     outCharacteristic.serviceUuid = UUID::FromString(serviceUuid);
149     outCharacteristic.characteristicUuid = UUID::FromString(characterUuid);
150     outCharacteristic.characteristicValue = std::move(characterValue);
151     outCharacteristic.descriptors = std::move(descriptors);
152     outCharacteristic.properties = ConvertGattProperties(properties);
153     outCharacteristic.characteristicValueHandle = static_cast<uint16_t>(characteristicValueHandle);
154     outCharacteristic.permissions = ConvertGattPermissions(permissions);
155     return napi_ok;
156 }
157 
NapiParseGattDescriptor(napi_env env,napi_value object,NapiBleDescriptor & outDescriptor)158 napi_status NapiParseGattDescriptor(napi_env env, napi_value object, NapiBleDescriptor &outDescriptor)
159 {
160     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
161         "descriptorUuid", "descriptorValue", "descriptorHandle", "permissions"}));
162 
163     std::string serviceUuid {};
164     std::string characterUuid {};
165     std::string descriptorUuid {};
166     std::vector<uint8_t> descriptorValue {};
167     uint32_t descriptorHandle = 0;
168     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
169     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
170     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
171     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "descriptorUuid", descriptorUuid));
172     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "descriptorValue", descriptorValue));
173 
174     if (NapiIsObjectPropertyExist(env, object, "descriptorHandle")) {
175         NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, object, "descriptorHandle", descriptorHandle));
176         NAPI_BT_RETURN_IF(descriptorHandle > 0xFFFF, "Invalid descriptorHandle", napi_invalid_arg);
177     }
178     NapiGattPermission permissions = DEFAULT_GATT_PERMISSIONS;
179     if (NapiIsObjectPropertyExist(env, object, "permissions")) {
180         NAPI_BT_CALL_RETURN(NapiParseObjectGattPermissions(env, object, "permissions", permissions));
181     }
182 
183     outDescriptor.serviceUuid = UUID::FromString(serviceUuid);
184     outDescriptor.characteristicUuid = UUID::FromString(characterUuid);
185     outDescriptor.descriptorUuid = UUID::FromString(descriptorUuid);
186     outDescriptor.descriptorValue = std::move(descriptorValue);
187     outDescriptor.descriptorHandle = static_cast<uint16_t>(descriptorHandle);
188     outDescriptor.permissions = ConvertGattPermissions(permissions);
189     return napi_ok;
190 }
191 
NapiParseNotifyCharacteristic(napi_env env,napi_value object,NapiNotifyCharacteristic & outCharacter)192 napi_status NapiParseNotifyCharacteristic(napi_env env, napi_value object, NapiNotifyCharacteristic &outCharacter)
193 {
194     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
195         "characteristicValue", "confirm"}));
196 
197     std::string serviceUuid {};
198     std::string characterUuid {};
199     std::vector<uint8_t> characterValue {};
200     bool confirm = false;
201     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
202     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
203     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
204     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "characteristicValue", characterValue));
205     NAPI_BT_CALL_RETURN(NapiParseObjectBoolean(env, object, "confirm", confirm));
206 
207     outCharacter.serviceUuid = UUID::FromString(serviceUuid);
208     outCharacter.characterUuid = UUID::FromString(characterUuid);
209     outCharacter.characterValue = std::move(characterValue);
210     outCharacter.confirm = confirm;
211     return napi_ok;
212 }
213 
NapiParseGattsServerResponse(napi_env env,napi_value object,NapiGattsServerResponse & rsp)214 napi_status NapiParseGattsServerResponse(napi_env env, napi_value object, NapiGattsServerResponse &rsp)
215 {
216     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"deviceId", "transId", "status", "offset",
217         "value"}));
218 
219     std::string deviceId {};
220     int transId = 0;
221     int status = 0;
222     int offset = 0;
223     std::vector<uint8_t> value {};
224     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
225     NAPI_BT_CALL_RETURN(NapiParseObjectBdAddr(env, object, "deviceId", deviceId));
226     NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "transId", transId));
227     NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "status", status));
228     NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "offset", offset));
229     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "value", value));
230 
231     rsp.deviceId = deviceId;
232     rsp.transId = transId;
233     rsp.status = status;
234     rsp.offset = offset;
235     rsp.value = std::move(value);
236     return napi_ok;
237 }
238 
NapiParseObjectGattPermissions(napi_env env,napi_value object,const char * name,NapiGattPermission & outPermissions)239 napi_status NapiParseObjectGattPermissions(napi_env env, napi_value object, const char *name,
240     NapiGattPermission &outPermissions)
241 {
242     napi_value permissionObject;
243     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
244     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, permissionObject));
245     // Parse permission object
246     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, permissionObject, {"readable", "writeable",
247         "readEncrypted", "writeEncrypted"}));
248 
249     bool isExist;
250     NapiGattPermission permissions {};
251     NAPI_BT_CALL_RETURN(
252         NapiParseObjectBooleanOptional(env, permissionObject, "readable", permissions.readable, isExist));
253     NAPI_BT_CALL_RETURN(
254         NapiParseObjectBooleanOptional(env, permissionObject, "writeable", permissions.writeable, isExist));
255     NAPI_BT_CALL_RETURN(
256         NapiParseObjectBooleanOptional(env, permissionObject, "readEncrypted", permissions.readEncrypted, isExist));
257     NAPI_BT_CALL_RETURN(
258         NapiParseObjectBooleanOptional(env, permissionObject, "writeEncrypted", permissions.writeEncrypted, isExist));
259     outPermissions = permissions;
260     return napi_ok;
261 }
262 
NapiParseObjectGattProperties(napi_env env,napi_value object,const char * name,NapiGattProperties & outProperties)263 napi_status NapiParseObjectGattProperties(napi_env env, napi_value object, const char *name,
264     NapiGattProperties &outProperties)
265 {
266     napi_value propertiesObject;
267     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
268     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, propertiesObject));
269     // Parse properties object
270     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, propertiesObject, {"write", "writeNoResponse",
271         "read", "notify", "indicate"}));
272 
273     bool isExist;
274     NapiGattProperties properties {};
275     NAPI_BT_CALL_RETURN(
276         NapiParseObjectBooleanOptional(env, propertiesObject, "write", properties.write, isExist));
277     NAPI_BT_CALL_RETURN(
278         NapiParseObjectBooleanOptional(env, propertiesObject, "writeNoResponse", properties.writeNoResponse, isExist));
279     NAPI_BT_CALL_RETURN(
280         NapiParseObjectBooleanOptional(env, propertiesObject, "read", properties.read, isExist));
281     NAPI_BT_CALL_RETURN(
282         NapiParseObjectBooleanOptional(env, propertiesObject, "notify", properties.notify, isExist));
283     NAPI_BT_CALL_RETURN(
284         NapiParseObjectBooleanOptional(env, propertiesObject, "indicate", properties.indicate, isExist));
285     outProperties = properties;
286     return napi_ok;
287 }
288 
NapiParseBoolean(napi_env env,napi_value value,bool & outBoolean)289 napi_status NapiParseBoolean(napi_env env, napi_value value, bool &outBoolean)
290 {
291     bool boolean = false;
292     NAPI_BT_CALL_RETURN(NapiIsBoolean(env, value));
293     NAPI_BT_CALL_RETURN(napi_get_value_bool(env, value, &boolean));
294     outBoolean = boolean;
295     return napi_ok;
296 }
297 
NapiParseInt32(napi_env env,napi_value value,int32_t & outNum)298 napi_status NapiParseInt32(napi_env env, napi_value value, int32_t &outNum)
299 {
300     int32_t num = 0;
301     NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
302     NAPI_BT_CALL_RETURN(napi_get_value_int32(env, value, &num));
303     outNum = num;
304     return napi_ok;
305 }
306 
NapiParseUint32(napi_env env,napi_value value,uint32_t & outNum)307 napi_status NapiParseUint32(napi_env env, napi_value value, uint32_t &outNum)
308 {
309     uint32_t num = 0;
310     NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
311     NAPI_BT_CALL_RETURN(napi_get_value_uint32(env, value, &num));
312     outNum = num;
313     return napi_ok;
314 }
315 
NapiParseString(napi_env env,napi_value value,std::string & outStr)316 napi_status NapiParseString(napi_env env, napi_value value, std::string &outStr)
317 {
318     std::string str {};
319     NAPI_BT_CALL_RETURN(NapiIsString(env, value));
320     NAPI_BT_RETURN_IF(!ParseString(env, str, value), "parse string failed", napi_invalid_arg);
321     outStr = std::move(str);
322     return napi_ok;
323 }
324 
NapiParseStringArray(napi_env env,napi_value value,std::vector<std::string> & outStrVec)325 napi_status NapiParseStringArray(napi_env env, napi_value value, std::vector<std::string> &outStrVec)
326 {
327     NAPI_BT_CALL_RETURN(NapiIsArray(env, value));
328     uint32_t length = 0;
329     std::string param {};
330     std::vector<std::string> strVec {};
331     napi_get_array_length(env, value, &length);
332     for (size_t i = 0; i < length; i++) {
333         napi_value result;
334         napi_get_element(env, value, i, &result);
335         NAPI_BT_CALL_RETURN(NapiParseString(env, result, param));
336         strVec.push_back(param);
337     }
338     outStrVec = std::move(strVec);
339     return napi_ok;
340 }
341 
NapiParseFileHolderArray(napi_env env,napi_value value,std::vector<FileHolder> & outFileHolderVec)342 napi_status NapiParseFileHolderArray(napi_env env, napi_value value, std::vector<FileHolder> &outFileHolderVec)
343 {
344     NAPI_BT_CALL_RETURN(NapiIsArray(env, value));
345     uint32_t length = 0;
346     std::vector<FileHolder> fileHolderVec {};
347     napi_get_array_length(env, value, &length);
348     for (uint32_t i = 0; i < length; i++) {
349         FileHolder fileHolder;
350         napi_value result;
351         napi_get_element(env, value, i, &result);
352         NAPI_BT_CALL_RETURN(NapiParseFileHolder(env, result, fileHolder));
353         fileHolderVec.push_back(fileHolder);
354     }
355     outFileHolderVec = std::move(fileHolderVec);
356     return napi_ok;
357 }
358 
NapiParseFileHolder(napi_env env,napi_value object,FileHolder & outFileHolder)359 napi_status NapiParseFileHolder(napi_env env, napi_value object, FileHolder &outFileHolder)
360 {
361     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"filePath", "fileSize", "fileFd"}));
362     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
363     std::string filePath {};
364     int64_t fileSize = 0;
365     int32_t fileFd = 0;
366     std::string fileType {};
367 
368     NAPI_BT_CALL_RETURN(NapiParseObjectString(env, object, "filePath", filePath));
369     NAPI_BT_CALL_RETURN(NapiParseObjectInt64(env, object, "fileSize", fileSize));
370     NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "fileFd", fileFd));
371     HILOGI("fileSize: %{public}" PRId64 " fileFd: %{public}d", fileSize, fileFd);
372 
373     FileHolder fileHolder;
374     fileHolder.filePath = filePath;
375     fileHolder.fileSize = fileSize;
376     fileHolder.fileFd = fileFd;
377     outFileHolder = std::move(fileHolder);
378     return napi_ok;
379 }
380 
381 
NapiParseBdAddr(napi_env env,napi_value value,std::string & outAddr)382 napi_status NapiParseBdAddr(napi_env env, napi_value value, std::string &outAddr)
383 {
384     std::string bdaddr {};
385     NAPI_BT_CALL_RETURN(NapiParseString(env, value, bdaddr));
386     NAPI_BT_RETURN_IF(!IsValidAddress(bdaddr), "Invalid bdaddr", napi_invalid_arg);
387     outAddr = std::move(bdaddr);
388     return napi_ok;
389 }
390 
NapiParseUuid(napi_env env,napi_value value,std::string & outUuid)391 napi_status NapiParseUuid(napi_env env, napi_value value, std::string &outUuid)
392 {
393     std::string uuid {};
394     NAPI_BT_CALL_RETURN(NapiParseString(env, value, uuid));
395     NAPI_BT_RETURN_IF(!IsValidUuid(uuid), "Invalid uuid", napi_invalid_arg);
396     outUuid = std::move(uuid);
397     return napi_ok;
398 }
399 
NapiParseInt64(napi_env env,napi_value value,int64_t & outNum)400 napi_status NapiParseInt64(napi_env env, napi_value value, int64_t &outNum)
401 {
402     int64_t num = 0;
403     NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
404     NAPI_BT_CALL_RETURN(napi_get_value_int64(env, value, &num));
405     outNum = num;
406     return napi_ok;
407 }
408 
NapiParseObjectInt64(napi_env env,napi_value object,const char * name,int64_t & outNum)409 napi_status NapiParseObjectInt64(napi_env env, napi_value object, const char *name, int64_t &outNum)
410 {
411     napi_value property;
412     int64_t num = 0;
413     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
414     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
415     NAPI_BT_CALL_RETURN(NapiParseInt64(env, property, num));
416     outNum = num;
417     return napi_ok;
418 }
419 
NapiParseObjectStr(napi_env env,napi_value object,const char * name,std::string & outStr)420 napi_status NapiParseObjectStr(napi_env env, napi_value object, const char *name, std::string &outStr)
421 {
422     napi_value property;
423     std::string str;
424     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
425     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
426     NAPI_BT_CALL_RETURN(NapiParseString(env, property, str));
427     outStr = std::move(str);
428     return napi_ok;
429 }
430 
NapiParseObjectUuids(napi_env env,napi_value object,const char * name,std::vector<std::string> & outUuid)431 napi_status NapiParseObjectUuids(napi_env env, napi_value object, const char *name, std::vector<std::string> &outUuid)
432 {
433     std::string uuids;
434     NAPI_BT_CALL_RETURN(NapiParseObjectStr(env, object, name, uuids));
435     NAPI_BT_CALL_RETURN(ParseAndCheckUuids(uuids, outUuid));
436     return napi_ok;
437 }
438 
ParseAndCheckUuids(const std::string & uuids,std::vector<std::string> & res)439 napi_status ParseAndCheckUuids(const std::string &uuids, std::vector<std::string> &res)
440 {
441     HILOGI("[CLOUD_PAIR] ParseAndCheckUuids %{public}s", uuids.c_str());
442     if (uuids.empty()) {
443         return napi_ok;
444     }
445     const std::regex pattern("[,]");
446     std::vector<std::string> result(
447         std::sregex_token_iterator(uuids.begin(), uuids.end(), pattern, -1),
448         std::sregex_token_iterator()
449     );
450     for (const auto &str : result) {
451         NAPI_BT_RETURN_IF(!IsValidUuid(str), "Invalid uuid", napi_invalid_arg);
452     }
453     res = std::move(result);
454     return napi_ok;
455 }
456 
NapiParseTrustPairDevice(napi_env env,napi_value object,std::vector<TrustPairDeviceParam> & outService)457 napi_status NapiParseTrustPairDevice(napi_env env, napi_value object, std::vector<TrustPairDeviceParam> &outService)
458 {
459     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"trustedPairedDevices"}));
460     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "trustedPairedDevices", outService));
461     return napi_ok;
462 }
463 
NapiParseArrayBuffer(napi_env env,napi_value value,std::vector<uint8_t> & outVec)464 napi_status NapiParseArrayBuffer(napi_env env, napi_value value, std::vector<uint8_t> &outVec)
465 {
466     uint8_t *data = nullptr;
467     size_t size = 0;
468     NAPI_BT_CALL_RETURN(NapiIsArrayBuffer(env, value));
469     bool isSuccess = ParseArrayBuffer(env, &data, size, value);
470     if (!isSuccess) {
471         HILOGE("Parse arraybuffer failed");
472         return napi_invalid_arg;
473     }
474     std::vector<uint8_t> vec(data, data + size);
475     outVec = std::move(vec);
476     return napi_ok;
477 }
478 
NapiParseGattWriteType(napi_env env,napi_value value,int & outWriteType)479 napi_status NapiParseGattWriteType(napi_env env, napi_value value, int &outWriteType)
480 {
481     int writeType = -1;
482     NAPI_BT_CALL_RETURN(NapiParseInt32(env, value, writeType));
483     if (writeType == static_cast<int>(NapiGattWriteType::WRITE)) {
484         HILOGI("gattWriteType: WRITE");
485         outWriteType = GattCharacteristic::WriteType::DEFAULT;
486     } else if (writeType == static_cast<int>(NapiGattWriteType::WRITE_NO_RESPONSE)) {
487         HILOGI("gattWriteType: WRITE_NO_RESPONSE");
488         outWriteType = GattCharacteristic::WriteType::NO_RESPONSE;
489     } else {
490         HILOGE("Invalid gattWriteType: %{public}d", writeType);
491         return napi_invalid_arg;
492     }
493     return napi_ok;
494 }
495 
NapiParseAsyncCallback(napi_env env,napi_callback_info info)496 std::shared_ptr<NapiAsyncCallback> NapiParseAsyncCallback(napi_env env, napi_callback_info info)
497 {
498     size_t argc = ARGS_SIZE_FOUR;
499     napi_value argv[ARGS_SIZE_FOUR] = {nullptr};
500     auto status = napi_get_cb_info(env, info, &argc, argv, nullptr, NULL);
501     if (status != napi_ok) {
502         HILOGE("napi_get_cb_info failed");
503         return nullptr;
504     }
505     if (argc > ARGS_SIZE_FOUR) {
506         HILOGE("size of parameters is larger than ARGS_SIZE_FOUR");
507         return nullptr;
508     }
509 
510     // "argc - 1" is AsyncCallback parameter's index
511     auto asyncCallback = std::make_shared<NapiAsyncCallback>();
512     asyncCallback->env = env;
513     if (argc > 0 && NapiIsFunction(env, argv[argc - 1]) == napi_ok) {
514         HILOGD("callback mode");
515         asyncCallback->callback = std::make_shared<NapiCallback>(env, argv[argc - 1]);
516     } else {
517         HILOGD("promise mode");
518         asyncCallback->promise = std::make_shared<NapiPromise>(env);
519     }
520     return asyncCallback;
521 }
522 
NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)523 static napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty,
524     bool &outExist)
525 {
526     bool exist = false;
527     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
528     NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &exist));
529     if (exist) {
530         napi_value property;
531         NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
532         outProperty = property;
533     }
534     outExist = exist;
535     return napi_ok;
536 }
NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty)537 napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty)
538 {
539     bool exist = false;
540     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, outProperty, exist));
541     NAPI_BT_RETURN_IF(!exist, "no needed property", napi_invalid_arg);
542     return napi_ok;
543 }
NapiGetObjectPropertyOptional(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)544 napi_status NapiGetObjectPropertyOptional(napi_env env, napi_value object, const char *name, napi_value &outProperty,
545     bool &outExist)
546 {
547     return NapiGetObjectProperty(env, object, name, outProperty, outExist);
548 }
549 
NapiParseObjectBoolean(napi_env env,napi_value object,const char * name,bool & outBoolean)550 napi_status NapiParseObjectBoolean(napi_env env, napi_value object, const char *name, bool &outBoolean)
551 {
552     napi_value property;
553     bool boolean = true;
554     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
555     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
556     NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean));
557     outBoolean = boolean;
558     return napi_ok;
559 }
560 
NapiParseObjectUuid(napi_env env,napi_value object,const char * name,std::string & outUuid)561 napi_status NapiParseObjectUuid(napi_env env, napi_value object, const char *name, std::string &outUuid)
562 {
563     napi_value property;
564     std::string uuid {};
565     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
566     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
567     NAPI_BT_CALL_RETURN(NapiParseUuid(env, property, uuid));
568     outUuid = std::move(uuid);
569     return napi_ok;
570 }
571 
NapiParseObjectArrayBuffer(napi_env env,napi_value object,const char * name,std::vector<uint8_t> & outVec)572 napi_status NapiParseObjectArrayBuffer(napi_env env, napi_value object, const char *name, std::vector<uint8_t> &outVec)
573 {
574     napi_value property;
575     std::vector<uint8_t> vec {};
576     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
577     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
578     NAPI_BT_CALL_RETURN(NapiParseArrayBuffer(env, property, vec));
579     outVec = std::move(vec);
580     return napi_ok;
581 }
582 
NapiParseObjectBdAddr(napi_env env,napi_value object,const char * name,std::string & outAddr)583 napi_status NapiParseObjectBdAddr(napi_env env, napi_value object, const char *name, std::string &outAddr)
584 {
585     napi_value property;
586     std::string bdaddr {};
587     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
588     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
589     NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, property, bdaddr));
590     outAddr = std::move(bdaddr);
591     return napi_ok;
592 }
593 
NapiParseObjectInt32(napi_env env,napi_value object,const char * name,int32_t & outNum)594 napi_status NapiParseObjectInt32(napi_env env, napi_value object, const char *name, int32_t &outNum)
595 {
596     napi_value property;
597     int32_t num = 0;
598     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
599     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
600     NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num));
601     outNum = num;
602     return napi_ok;
603 }
604 
NapiParseObjectString(napi_env env,napi_value object,const char * name,std::string & outString)605 napi_status NapiParseObjectString(napi_env env, napi_value object, const char *name, std::string &outString)
606 {
607     napi_value property;
608     std::string str = "";
609     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
610     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
611     NAPI_BT_CALL_RETURN(NapiParseString(env, property, str));
612     outString = str;
613     return napi_ok;
614 }
615 
NapiParseObjectUint32(napi_env env,napi_value object,const char * name,uint32_t & outNum)616 napi_status NapiParseObjectUint32(napi_env env, napi_value object, const char *name, uint32_t &outNum)
617 {
618     napi_value property;
619     uint32_t num = 0;
620     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
621     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
622     NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num));
623     outNum = num;
624     return napi_ok;
625 }
626 
NapiParseObjectUint32Check(NapiObject napiObject,const char * name,uint32_t & outNum,uint32_t min,uint32_t max)627 napi_status NapiParseObjectUint32Check(NapiObject napiObject, const char *name, uint32_t &outNum,
628     uint32_t min, uint32_t max)
629 {
630     NAPI_BT_CALL_RETURN(NapiParseObjectUint32(napiObject.env, napiObject.object, name, outNum));
631     if (outNum < min || outNum > max) {
632         return napi_invalid_arg;
633     }
634     return napi_ok;
635 }
636 
NapiParseObjectBooleanOptional(napi_env env,napi_value object,const char * name,bool & outBoolean,bool & outExist)637 napi_status NapiParseObjectBooleanOptional(napi_env env, napi_value object, const char *name, bool &outBoolean,
638     bool &outExist)
639 {
640     napi_value property;
641     bool exist = false;
642     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
643     NAPI_BT_CALL_RETURN(NapiGetObjectPropertyOptional(env, object, name, property, exist));
644     if (exist) {
645         bool boolean = true;
646         NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean));
647         outBoolean = boolean;
648     }
649     outExist = exist;
650     return napi_ok;
651 }
NapiParseObjectInt32Optional(napi_env env,napi_value object,const char * name,int32_t & outNum,bool & outExist)652 napi_status NapiParseObjectInt32Optional(napi_env env, napi_value object, const char *name, int32_t &outNum,
653     bool &outExist)
654 {
655     napi_value property;
656     bool exist = false;
657     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
658     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist));
659     if (exist) {
660         int32_t num = 0;
661         NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num));
662         outNum = num;
663     }
664     outExist = exist;
665     return napi_ok;
666 }
NapiParseObjectUint32Optional(napi_env env,napi_value object,const char * name,uint32_t & outNum,bool & outExist)667 napi_status NapiParseObjectUint32Optional(napi_env env, napi_value object, const char *name, uint32_t &outNum,
668     bool &outExist)
669 {
670     napi_value property;
671     bool exist = false;
672     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
673     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist));
674     if (exist) {
675         uint32_t num = 0;
676         NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num));
677         outNum = num;
678     }
679     outExist = exist;
680     return napi_ok;
681 }
682 
683 // Parse params template, used for NapiParseArray
684 template <typename T>
NapiParseObject(napi_env env,napi_value object,T & outObj)685 napi_status NapiParseObject(napi_env env, napi_value object, T &outObj)
686 {
687     HILOGE("Unimpleted type");
688     return napi_invalid_arg;
689 }
690 
691 template <>
NapiParseObject(napi_env env,napi_value object,std::string & outObj)692 napi_status NapiParseObject<std::string>(napi_env env, napi_value object, std::string &outObj)
693 {
694     return NapiParseString(env, object, outObj);
695 }
696 
697 template <>
NapiParseObject(napi_env env,napi_value object,UUID & outObj)698 napi_status NapiParseObject<UUID>(napi_env env, napi_value object, UUID &outObj)
699 {
700     std::string uuid {};
701     NAPI_BT_CALL_RETURN(NapiParseUuid(env, object, uuid));
702     outObj = UUID::FromString(uuid);
703     return napi_ok;
704 }
705 
706 template <>
NapiParseObject(napi_env env,napi_value object,NapiAdvManufactureData & outObj)707 napi_status NapiParseObject<NapiAdvManufactureData>(napi_env env, napi_value object, NapiAdvManufactureData &outObj)
708 {
709     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"manufactureId", "manufactureValue"}));
710     uint32_t num = 0;
711     std::vector<uint8_t> vec {};
712     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
713     NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, object, "manufactureId", num));
714     NAPI_BT_RETURN_IF(num > 0xFFFF, "Invalid manufactureId", napi_invalid_arg);
715     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "manufactureValue", vec));
716 
717     outObj.id = static_cast<uint16_t>(num);
718     outObj.value = std::string(vec.begin(), vec.end());
719     return napi_ok;
720 }
721 
722 template <>
NapiParseObject(napi_env env,napi_value object,NapiAdvServiceData & outObj)723 napi_status NapiParseObject<NapiAdvServiceData>(napi_env env, napi_value object, NapiAdvServiceData &outObj)
724 {
725     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "serviceValue"}));
726     std::string uuid {};
727     std::vector<uint8_t> vec {};
728     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
729     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", uuid));
730     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "serviceValue", vec));
731 
732     outObj.uuid = std::move(uuid);
733     outObj.value = std::move(vec);
734     return napi_ok;
735 }
736 
737 template <>
NapiParseObject(napi_env env,napi_value object,NapiGattService & outObj)738 napi_status NapiParseObject<NapiGattService>(napi_env env, napi_value object, NapiGattService &outObj)
739 {
740     return NapiParseGattService(env, object, outObj);
741 }
742 
743 template <>
NapiParseObject(napi_env env,napi_value object,NapiBleCharacteristic & outObj)744 napi_status NapiParseObject<NapiBleCharacteristic>(napi_env env, napi_value object, NapiBleCharacteristic &outObj)
745 {
746     return NapiParseGattCharacteristic(env, object, outObj);
747 }
748 
749 template <>
NapiParseObject(napi_env env,napi_value object,NapiBleDescriptor & outObj)750 napi_status NapiParseObject<NapiBleDescriptor>(napi_env env, napi_value object, NapiBleDescriptor &outObj)
751 {
752     return NapiParseGattDescriptor(env, object, outObj);
753 }
754 
755 template <>
NapiParseObject(napi_env env,napi_value object,TrustPairDeviceParam & outObj)756 napi_status NapiParseObject<TrustPairDeviceParam>(napi_env env, napi_value object, TrustPairDeviceParam &outObj)
757 {
758     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"sn", "deviceType",
759         "modelId", "manufactory", "productId", "hiLinkVersion", "macAddress", "serviceType",
760         "serviceId", "deviceName", "uuids", "bluetoothClass", "token", "deviceNameTime",
761         "secureAdvertisingInfo", "pairState"}));
762     NapiParseObjectStr(env, object, "sn", outObj.sn_);
763     NapiParseObjectStr(env, object, "deviceType", outObj.deviceType_);
764     NapiParseObjectStr(env, object, "modelId", outObj.modelId_);
765     NapiParseObjectStr(env, object, "manufactory", outObj.manufactory_);
766     NapiParseObjectStr(env, object, "productId", outObj.productId_);
767     NapiParseObjectStr(env, object, "hiLinkVersion", outObj.hiLinkVersion_);
768     NAPI_BT_CALL_RETURN(NapiParseObjectBdAddr(env, object, "macAddress", outObj.macAddress_));
769     NapiParseObjectStr(env, object, "serviceType", outObj.serviceType_);
770     NapiParseObjectStr(env, object, "serviceId", outObj.serviceId_);
771     NapiParseObjectStr(env, object, "deviceName", outObj.deviceName_);
772     NAPI_BT_CALL_RETURN(NapiParseObjectUuids(env, object, "uuids", outObj.uuids_));
773     NapiParseObjectInt32(env, object, "bluetoothClass", outObj.bluetoothClass_);
774     NapiParseObjectInt64(env, object, "deviceNameTime", outObj.deviceNameTime_);
775     NapiParseObjectInt32(env, object, "pairState", outObj.pairState_);
776     std::vector<uint8_t> tokenValue;
777     std::vector<uint8_t> secureAdvertisingInfoValue;
778     NapiParseObjectArrayBuffer(env, object, "token", tokenValue);
779     NapiParseObjectArrayBuffer(env, object, "secureAdvertisingInfo", secureAdvertisingInfoValue);
780     outObj.token_ = std::move(tokenValue);
781     outObj.secureAdvertisingInfo_ = std::move(secureAdvertisingInfoValue);
782     return napi_ok;
783 }
784 
785 template <typename T>
NapiParseArray(napi_env env,napi_value array,std::vector<T> & outVec)786 napi_status NapiParseArray(napi_env env, napi_value array, std::vector<T> &outVec)
787 {
788     std::vector<T> vec {};
789 
790     NAPI_BT_CALL_RETURN(NapiIsArray(env, array));
791     uint32_t length = 0;
792     NAPI_BT_CALL_RETURN(napi_get_array_length(env, array, &length));
793     for (uint32_t i = 0; i < length; ++i) {
794         napi_value element;
795         NAPI_BT_CALL_RETURN(napi_get_element(env, array, i, &element));
796         T object;
797         NAPI_BT_CALL_RETURN(NapiParseObject(env, element, object));
798         vec.push_back(std::move(object));
799     }
800     outVec = std::move(vec);
801     return napi_ok;
802 }
803 // // Declaration, ohters will undefined synbol
804 template napi_status NapiParseArray<NapiBleDescriptor>(napi_env env, napi_value array,
805     std::vector<NapiBleDescriptor> &outVec);
806 template napi_status NapiParseArray<NapiBleCharacteristic>(napi_env env, napi_value array,
807     std::vector<NapiBleCharacteristic> &outVec);
808 template napi_status NapiParseArray<NapiGattService>(napi_env env, napi_value array,
809     std::vector<NapiGattService> &outVec);
810 template napi_status NapiParseArray<NapiAdvServiceData>(napi_env env, napi_value array,
811     std::vector<NapiAdvServiceData> &outVec);
812 template napi_status NapiParseArray<NapiAdvManufactureData>(napi_env env, napi_value array,
813     std::vector<NapiAdvManufactureData> &outVec);
814 template napi_status NapiParseArray<UUID>(napi_env env, napi_value array,
815     std::vector<UUID> &outVec);
816 template napi_status NapiParseArray<std::string>(napi_env env, napi_value array,
817     std::vector<std::string> &outVec);
818 template napi_status NapiParseArray<TrustPairDeviceParam>(napi_env env, napi_value array,
819     std::vector<TrustPairDeviceParam> &outVec);
820 
821 template <typename T>
NapiParseObjectArray(napi_env env,napi_value object,const char * name,std::vector<T> & outVec)822 napi_status NapiParseObjectArray(napi_env env, napi_value object, const char *name, std::vector<T> &outVec)
823 {
824     napi_value property;
825     std::vector<T> vec {};
826     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
827     NAPI_BT_CALL_RETURN(NapiParseArray(env, property, vec));
828     outVec = std::move(vec);
829     return napi_ok;
830 }
831 // Declaration, ohters will undefined synbol
832 template napi_status NapiParseObjectArray<NapiBleDescriptor>(napi_env env, napi_value object, const char *name,
833     std::vector<NapiBleDescriptor> &outVec);
834 template napi_status NapiParseObjectArray<NapiBleCharacteristic>(napi_env env, napi_value object, const char *name,
835     std::vector<NapiBleCharacteristic> &outVec);
836 template napi_status NapiParseObjectArray<NapiGattService>(napi_env env, napi_value object, const char *name,
837     std::vector<NapiGattService> &outVec);
838 template napi_status NapiParseObjectArray<NapiAdvServiceData>(napi_env env, napi_value object, const char *name,
839     std::vector<NapiAdvServiceData> &outVec);
840 template napi_status NapiParseObjectArray<NapiAdvManufactureData>(napi_env env, napi_value object, const char *name,
841     std::vector<NapiAdvManufactureData> &outVec);
842 template napi_status NapiParseObjectArray<UUID>(napi_env env, napi_value object, const char *name,
843     std::vector<UUID> &outVec);
844 template napi_status NapiParseObjectArray<std::string>(napi_env env, napi_value object, const char *name,
845     std::vector<std::string> &outVec);
846 template napi_status NapiParseObjectArray<TrustPairDeviceParam>(napi_env env, napi_value object, const char *name,
847     std::vector<TrustPairDeviceParam> &outVec);
848 }  // namespace Bluetooth
849 }  // namespace OHOS
850