• 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 namespace OHOS {
22 namespace Bluetooth {
23 
24 // shall check object type is napi_object before, if it's other type, return false
25 // If the 'name' field is not exist, or napi function call error, return false
NapiIsObjectPropertyExist(napi_env env,napi_value object,const char * name)26 static bool NapiIsObjectPropertyExist(napi_env env, napi_value object, const char *name)
27 {
28     auto status = NapiIsObject(env, object);
29     if (status != napi_ok) {
30         HILOGE("expect object");
31         return false;
32     }
33     bool exist = false;
34     status = napi_has_named_property(env, object, name, &exist);
35     if (status != napi_ok) {
36         HILOGE("Get object property failed, name: %{public}s", name);
37         return false;
38     }
39     return exist;
40 }
41 
NapiParseGattService(napi_env env,napi_value object,NapiGattService & outService)42 napi_status NapiParseGattService(napi_env env, napi_value object, NapiGattService &outService)
43 {
44     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "isPrimary", "characteristics",
45         "includeServices"}));
46 
47     std::string uuid {};
48     bool isPrimary = true;
49     std::vector<NapiBleCharacteristic> characteristics {};
50     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
51     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", uuid));
52     NAPI_BT_CALL_RETURN(NapiParseObjectBoolean(env, object, "isPrimary", isPrimary));
53     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "characteristics", characteristics));
54     if (NapiIsObjectPropertyExist(env, object, "includeServices")) {
55         std::vector<NapiGattService> includeServices {};
56         NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "includeServices", includeServices));
57         outService.includeServices = std::move(includeServices);
58     }
59     outService.serviceUuid = UUID::FromString(uuid);
60     outService.isPrimary = isPrimary;
61     outService.characteristics = std::move(characteristics);
62     return napi_ok;
63 }
64 
NapiParseGattCharacteristic(napi_env env,napi_value object,NapiBleCharacteristic & outCharacteristic)65 napi_status NapiParseGattCharacteristic(napi_env env, napi_value object, NapiBleCharacteristic &outCharacteristic)
66 {
67     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
68         "characteristicValue", "descriptors"}));
69 
70     std::string serviceUuid {};
71     std::string characterUuid {};
72     std::vector<uint8_t> characterValue {};
73     std::vector<NapiBleDescriptor> descriptors {};
74     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
75     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
76     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
77     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "characteristicValue", characterValue));
78     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "descriptors", descriptors));
79 
80     outCharacteristic.serviceUuid = UUID::FromString(serviceUuid);
81     outCharacteristic.characteristicUuid = UUID::FromString(characterUuid);
82     outCharacteristic.characteristicValue = std::move(characterValue);
83     outCharacteristic.descriptors = std::move(descriptors);
84     return napi_ok;
85 }
86 
NapiParseGattDescriptor(napi_env env,napi_value object,NapiBleDescriptor & outDescriptor)87 napi_status NapiParseGattDescriptor(napi_env env, napi_value object, NapiBleDescriptor &outDescriptor)
88 {
89     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
90         "descriptorUuid", "descriptorValue"}));
91 
92     std::string serviceUuid {};
93     std::string characterUuid {};
94     std::string descriptorUuid {};
95     std::vector<uint8_t> descriptorValue {};
96     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
97     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
98     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
99     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "descriptorUuid", descriptorUuid));
100     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "descriptorValue", descriptorValue));
101 
102     outDescriptor.serviceUuid = UUID::FromString(serviceUuid);
103     outDescriptor.characteristicUuid = UUID::FromString(characterUuid);
104     outDescriptor.descriptorUuid = UUID::FromString(descriptorUuid);
105     outDescriptor.descriptorValue = std::move(descriptorValue);
106     return napi_ok;
107 }
108 
NapiParseNotifyCharacteristic(napi_env env,napi_value object,NapiNotifyCharacteristic & outCharacter)109 napi_status NapiParseNotifyCharacteristic(napi_env env, napi_value object, NapiNotifyCharacteristic &outCharacter)
110 {
111     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
112         "characteristicValue", "confirm"}));
113 
114     std::string serviceUuid {};
115     std::string characterUuid {};
116     std::vector<uint8_t> characterValue {};
117     bool confirm = false;
118     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
119     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
120     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
121     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "characteristicValue", characterValue));
122     NAPI_BT_CALL_RETURN(NapiParseObjectBoolean(env, object, "confirm", confirm));
123 
124     outCharacter.serviceUuid = UUID::FromString(serviceUuid);
125     outCharacter.characterUuid = UUID::FromString(characterUuid);
126     outCharacter.characterValue = std::move(characterValue);
127     outCharacter.confirm = confirm;
128     return napi_ok;
129 }
130 
NapiParseGattsServerResponse(napi_env env,napi_value object,NapiGattsServerResponse & rsp)131 napi_status NapiParseGattsServerResponse(napi_env env, napi_value object, NapiGattsServerResponse &rsp)
132 {
133     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"deviceId", "transId", "status", "offset",
134         "value"}));
135 
136     std::string deviceId {};
137     int transId = 0;
138     int status = 0;
139     int offset = 0;
140     std::vector<uint8_t> value {};
141     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
142     NAPI_BT_CALL_RETURN(NapiParseObjectBdAddr(env, object, "deviceId", deviceId));
143     NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "transId", transId));
144     NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "status", status));
145     NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "offset", offset));
146     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "value", value));
147 
148     rsp.deviceId = deviceId;
149     rsp.transId = transId;
150     rsp.status = status;
151     rsp.offset = offset;
152     rsp.value = std::move(value);
153     return napi_ok;
154 }
155 
NapiParseBoolean(napi_env env,napi_value value,bool & outBoolean)156 napi_status NapiParseBoolean(napi_env env, napi_value value, bool &outBoolean)
157 {
158     bool boolean = false;
159     NAPI_BT_CALL_RETURN(NapiIsBoolean(env, value));
160     NAPI_BT_CALL_RETURN(napi_get_value_bool(env, value, &boolean));
161     outBoolean = boolean;
162     return napi_ok;
163 }
164 
NapiParseInt32(napi_env env,napi_value value,int32_t & outNum)165 napi_status NapiParseInt32(napi_env env, napi_value value, int32_t &outNum)
166 {
167     int32_t num = 0;
168     NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
169     NAPI_BT_CALL_RETURN(napi_get_value_int32(env, value, &num));
170     outNum = num;
171     return napi_ok;
172 }
173 
NapiParseUint32(napi_env env,napi_value value,uint32_t & outNum)174 napi_status NapiParseUint32(napi_env env, napi_value value, uint32_t &outNum)
175 {
176     uint32_t num = 0;
177     NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
178     NAPI_BT_CALL_RETURN(napi_get_value_uint32(env, value, &num));
179     outNum = num;
180     return napi_ok;
181 }
182 
NapiParseString(napi_env env,napi_value value,std::string & outStr)183 napi_status NapiParseString(napi_env env, napi_value value, std::string &outStr)
184 {
185     std::string str {};
186     NAPI_BT_CALL_RETURN(NapiIsString(env, value));
187     NAPI_BT_RETURN_IF(!ParseString(env, str, value), "parse string failed", napi_invalid_arg);
188     outStr = std::move(str);
189     return napi_ok;
190 }
191 
NapiParseBdAddr(napi_env env,napi_value value,std::string & outAddr)192 napi_status NapiParseBdAddr(napi_env env, napi_value value, std::string &outAddr)
193 {
194     std::string bdaddr {};
195     NAPI_BT_CALL_RETURN(NapiParseString(env, value, bdaddr));
196     NAPI_BT_RETURN_IF(!IsValidAddress(bdaddr), "Invalid bdaddr", napi_invalid_arg);
197     outAddr = std::move(bdaddr);
198     return napi_ok;
199 }
200 
NapiParseUuid(napi_env env,napi_value value,std::string & outUuid)201 napi_status NapiParseUuid(napi_env env, napi_value value, std::string &outUuid)
202 {
203     std::string uuid {};
204     NAPI_BT_CALL_RETURN(NapiParseString(env, value, uuid));
205     NAPI_BT_RETURN_IF(!IsValidUuid(uuid), "Invalid uuid", napi_invalid_arg);
206     outUuid = std::move(uuid);
207     return napi_ok;
208 }
209 
NapiParseArrayBuffer(napi_env env,napi_value value,std::vector<uint8_t> & outVec)210 napi_status NapiParseArrayBuffer(napi_env env, napi_value value, std::vector<uint8_t> &outVec)
211 {
212     uint8_t *data = nullptr;
213     size_t size = 0;
214     NAPI_BT_CALL_RETURN(NapiIsArrayBuffer(env, value));
215     bool isSuccess = ParseArrayBuffer(env, &data, size, value);
216     if (!isSuccess) {
217         HILOGE("Parse arraybuffer failed");
218         return napi_invalid_arg;
219     }
220     std::vector<uint8_t> vec(data, data + size);
221     outVec = std::move(vec);
222     return napi_ok;
223 }
224 
NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)225 static napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty,
226     bool &outExist)
227 {
228     bool exist = false;
229     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
230     NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &exist));
231     if (exist) {
232         napi_value property;
233         NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
234         outProperty = property;
235     }
236     outExist = exist;
237     return napi_ok;
238 }
NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty)239 napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty)
240 {
241     bool exist = false;
242     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, outProperty, exist));
243     NAPI_BT_RETURN_IF(!exist, "no needed property", napi_invalid_arg);
244     return napi_ok;
245 }
NapiGetObjectPropertyOptional(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)246 napi_status NapiGetObjectPropertyOptional(napi_env env, napi_value object, const char *name, napi_value &outProperty,
247     bool &outExist)
248 {
249     return NapiGetObjectProperty(env, object, name, outProperty, outExist);
250 }
251 
NapiParseObjectBoolean(napi_env env,napi_value object,const char * name,bool & outBoolean)252 napi_status NapiParseObjectBoolean(napi_env env, napi_value object, const char *name, bool &outBoolean)
253 {
254     napi_value property;
255     bool boolean = true;
256     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
257     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
258     NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean));
259     outBoolean = boolean;
260     return napi_ok;
261 }
262 
NapiParseObjectUuid(napi_env env,napi_value object,const char * name,std::string & outUuid)263 napi_status NapiParseObjectUuid(napi_env env, napi_value object, const char *name, std::string &outUuid)
264 {
265     napi_value property;
266     std::string uuid {};
267     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
268     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
269     NAPI_BT_CALL_RETURN(NapiParseUuid(env, property, uuid));
270     outUuid = std::move(uuid);
271     return napi_ok;
272 }
273 
NapiParseObjectArrayBuffer(napi_env env,napi_value object,const char * name,std::vector<uint8_t> & outVec)274 napi_status NapiParseObjectArrayBuffer(napi_env env, napi_value object, const char *name, std::vector<uint8_t> &outVec)
275 {
276     napi_value property;
277     std::vector<uint8_t> vec {};
278     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
279     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
280     NAPI_BT_CALL_RETURN(NapiParseArrayBuffer(env, property, vec));
281     outVec = std::move(vec);
282     return napi_ok;
283 }
284 
NapiParseObjectBdAddr(napi_env env,napi_value object,const char * name,std::string & outAddr)285 napi_status NapiParseObjectBdAddr(napi_env env, napi_value object, const char *name, std::string &outAddr)
286 {
287     napi_value property;
288     std::string bdaddr {};
289     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
290     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
291     NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, property, bdaddr));
292     outAddr = std::move(bdaddr);
293     return napi_ok;
294 }
295 
NapiParseObjectInt32(napi_env env,napi_value object,const char * name,int32_t & outNum)296 napi_status NapiParseObjectInt32(napi_env env, napi_value object, const char *name, int32_t &outNum)
297 {
298     napi_value property;
299     int32_t num = 0;
300     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
301     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
302     NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num));
303     outNum = num;
304     return napi_ok;
305 }
306 
NapiParseObjectUint32(napi_env env,napi_value object,const char * name,uint32_t & outNum)307 napi_status NapiParseObjectUint32(napi_env env, napi_value object, const char *name, uint32_t &outNum)
308 {
309     napi_value property;
310     uint32_t num = 0;
311     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
312     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
313     NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num));
314     outNum = num;
315     return napi_ok;
316 }
317 
NapiParseObjectBooleanOptional(napi_env env,napi_value object,const char * name,bool & outBoolean,bool & outExist)318 napi_status NapiParseObjectBooleanOptional(napi_env env, napi_value object, const char *name, bool &outBoolean,
319     bool &outExist)
320 {
321     napi_value property;
322     bool boolean = true;
323     bool exist = false;
324     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
325     NAPI_BT_CALL_RETURN(NapiGetObjectPropertyOptional(env, object, name, property, exist));
326     if (exist) {
327         NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean));
328         outBoolean = boolean;
329     }
330     outExist = exist;
331     return napi_ok;
332 }
NapiParseObjectInt32Optional(napi_env env,napi_value object,const char * name,int32_t & outNum,bool & outExist)333 napi_status NapiParseObjectInt32Optional(napi_env env, napi_value object, const char *name, int32_t &outNum,
334     bool &outExist)
335 {
336     napi_value property;
337     int32_t num = 0;
338     bool exist = false;
339     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
340     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist));
341     if (exist) {
342         NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num));
343         outNum = num;
344     }
345     outExist = exist;
346     return napi_ok;
347 }
NapiParseObjectUint32Optional(napi_env env,napi_value object,const char * name,uint32_t & outNum,bool & outExist)348 napi_status NapiParseObjectUint32Optional(napi_env env, napi_value object, const char *name, uint32_t &outNum,
349     bool &outExist)
350 {
351     napi_value property;
352     uint32_t num = 0;
353     bool exist = false;
354     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
355     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist));
356     if (exist) {
357         NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num));
358         outNum = num;
359     }
360     outExist = exist;
361     return napi_ok;
362 }
363 
364 // Parse params template, used for NapiParseArray
365 template <typename T>
NapiParseObject(napi_env env,napi_value object,T & outObj)366 napi_status NapiParseObject(napi_env env, napi_value object, T &outObj)
367 {
368     HILOGE("Unimpleted type");
369     return napi_invalid_arg;
370 }
371 
372 template <>
NapiParseObject(napi_env env,napi_value object,std::string & outObj)373 napi_status NapiParseObject<std::string>(napi_env env, napi_value object, std::string &outObj)
374 {
375     return NapiParseString(env, object, outObj);
376 }
377 
378 template <>
NapiParseObject(napi_env env,napi_value object,UUID & outObj)379 napi_status NapiParseObject<UUID>(napi_env env, napi_value object, UUID &outObj)
380 {
381     std::string uuid {};
382     NAPI_BT_CALL_RETURN(NapiParseUuid(env, object, uuid));
383     outObj = UUID::FromString(uuid);
384     return napi_ok;
385 }
386 
387 template <>
NapiParseObject(napi_env env,napi_value object,NapiAdvManufactureData & outObj)388 napi_status NapiParseObject<NapiAdvManufactureData>(napi_env env, napi_value object, NapiAdvManufactureData &outObj)
389 {
390     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"manufactureId", "manufactureValue"}));
391     uint32_t num = 0;
392     std::vector<uint8_t> vec {};
393     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
394     NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, object, "manufactureId", num));
395     NAPI_BT_RETURN_IF(num > 0xFFFF, "Invalid manufactureId", napi_invalid_arg);
396     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "manufactureValue", vec));
397 
398     outObj.id = static_cast<uint16_t>(num);
399     outObj.value = std::string(vec.begin(), vec.end());
400     return napi_ok;
401 }
402 
403 template <>
NapiParseObject(napi_env env,napi_value object,NapiAdvServiceData & outObj)404 napi_status NapiParseObject<NapiAdvServiceData>(napi_env env, napi_value object, NapiAdvServiceData &outObj)
405 {
406     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "serviceValue"}));
407     std::string uuid {};
408     std::vector<uint8_t> vec {};
409     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
410     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", uuid));
411     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "serviceValue", vec));
412 
413     outObj.uuid = std::move(uuid);
414     outObj.value = std::move(vec);
415     return napi_ok;
416 }
417 
418 template <>
NapiParseObject(napi_env env,napi_value object,NapiGattService & outObj)419 napi_status NapiParseObject<NapiGattService>(napi_env env, napi_value object, NapiGattService &outObj)
420 {
421     return NapiParseGattService(env, object, outObj);
422 }
423 
424 template <>
NapiParseObject(napi_env env,napi_value object,NapiBleCharacteristic & outObj)425 napi_status NapiParseObject<NapiBleCharacteristic>(napi_env env, napi_value object, NapiBleCharacteristic &outObj)
426 {
427     return NapiParseGattCharacteristic(env, object, outObj);
428 }
429 
430 template <>
NapiParseObject(napi_env env,napi_value object,NapiBleDescriptor & outObj)431 napi_status NapiParseObject<NapiBleDescriptor>(napi_env env, napi_value object, NapiBleDescriptor &outObj)
432 {
433     return NapiParseGattDescriptor(env, object, outObj);
434 }
435 
436 template <typename T>
NapiParseArray(napi_env env,napi_value array,std::vector<T> & outVec)437 napi_status NapiParseArray(napi_env env, napi_value array, std::vector<T> &outVec)
438 {
439     std::vector<T> vec {};
440 
441     NAPI_BT_CALL_RETURN(NapiIsArray(env, array));
442     uint32_t length = 0;
443     NAPI_BT_CALL_RETURN(napi_get_array_length(env, array, &length));
444     for (uint32_t i = 0; i < length; ++i) {
445         napi_value element;
446         NAPI_BT_CALL_RETURN(napi_get_element(env, array, i, &element));
447         T object;
448         NAPI_BT_CALL_RETURN(NapiParseObject(env, element, object));
449         vec.push_back(std::move(object));
450     }
451     outVec = std::move(vec);
452     return napi_ok;
453 }
454 // // Declaration, ohters will undefined synbol
455 template napi_status NapiParseArray<NapiBleDescriptor>(napi_env env, napi_value array,
456     std::vector<NapiBleDescriptor> &outVec);
457 template napi_status NapiParseArray<NapiBleCharacteristic>(napi_env env, napi_value array,
458     std::vector<NapiBleCharacteristic> &outVec);
459 template napi_status NapiParseArray<NapiGattService>(napi_env env, napi_value array,
460     std::vector<NapiGattService> &outVec);
461 template napi_status NapiParseArray<NapiAdvServiceData>(napi_env env, napi_value array,
462     std::vector<NapiAdvServiceData> &outVec);
463 template napi_status NapiParseArray<NapiAdvManufactureData>(napi_env env, napi_value array,
464     std::vector<NapiAdvManufactureData> &outVec);
465 template napi_status NapiParseArray<UUID>(napi_env env, napi_value array,
466     std::vector<UUID> &outVec);
467 template napi_status NapiParseArray<std::string>(napi_env env, napi_value array,
468     std::vector<std::string> &outVec);
469 
470 
471 template <typename T>
NapiParseObjectArray(napi_env env,napi_value object,const char * name,std::vector<T> & outVec)472 napi_status NapiParseObjectArray(napi_env env, napi_value object, const char *name, std::vector<T> &outVec)
473 {
474     napi_value property;
475     std::vector<T> vec {};
476     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
477     NAPI_BT_CALL_RETURN(NapiParseArray(env, property, vec));
478     outVec = std::move(vec);
479     return napi_ok;
480 }
481 // Declaration, ohters will undefined synbol
482 template napi_status NapiParseObjectArray<NapiBleDescriptor>(napi_env env, napi_value object, const char *name,
483     std::vector<NapiBleDescriptor> &outVec);
484 template napi_status NapiParseObjectArray<NapiBleCharacteristic>(napi_env env, napi_value object, const char *name,
485     std::vector<NapiBleCharacteristic> &outVec);
486 template napi_status NapiParseObjectArray<NapiGattService>(napi_env env, napi_value object, const char *name,
487     std::vector<NapiGattService> &outVec);
488 template napi_status NapiParseObjectArray<NapiAdvServiceData>(napi_env env, napi_value object, const char *name,
489     std::vector<NapiAdvServiceData> &outVec);
490 template napi_status NapiParseObjectArray<NapiAdvManufactureData>(napi_env env, napi_value object, const char *name,
491     std::vector<NapiAdvManufactureData> &outVec);
492 template napi_status NapiParseObjectArray<UUID>(napi_env env, napi_value object, const char *name,
493     std::vector<UUID> &outVec);
494 template napi_status NapiParseObjectArray<std::string>(napi_env env, napi_value object, const char *name,
495     std::vector<std::string> &outVec);
496 }  // namespace Bluetooth
497 }  // namespace OHOS
498