1 /*
2  * Copyright (c) 2023 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 #define LOG_TAG "NapiDataUtils"
16 #include "napi_data_utils.h"
17 
18 namespace OHOS {
19 namespace UDMF {
20 constexpr int32_t STR_MAX_LENGTH = 4096;
21 constexpr size_t STR_TAIL_LENGTH = 1;
22 
23 /* napi_value <-> bool */
GetValue(napi_env env,napi_value in,bool & out)24 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, bool &out)
25 {
26     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- bool");
27     return napi_get_value_bool(env, in, &out);
28 }
29 
SetValue(napi_env env,const bool & in,napi_value & out)30 napi_status NapiDataUtils::SetValue(napi_env env, const bool &in, napi_value &out)
31 {
32     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> bool");
33     return napi_get_boolean(env, in, &out);
34 }
35 
36 /* napi_value <-> int32_t */
GetValue(napi_env env,napi_value in,int32_t & out)37 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, int32_t &out)
38 {
39     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> int32_t");
40     return napi_get_value_int32(env, in, &out);
41 }
42 
SetValue(napi_env env,const int32_t & in,napi_value & out)43 napi_status NapiDataUtils::SetValue(napi_env env, const int32_t &in, napi_value &out)
44 {
45     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- int32_t");
46     return napi_create_int32(env, in, &out);
47 }
48 
49 /* napi_value <-> int64_t */
GetValue(napi_env env,napi_value in,int64_t & out)50 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, int64_t &out)
51 {
52     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> int64_t");
53     return napi_get_value_int64(env, in, &out);
54 }
55 
SetValue(napi_env env,const int64_t & in,napi_value & out)56 napi_status NapiDataUtils::SetValue(napi_env env, const int64_t &in, napi_value &out)
57 {
58     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- int64_t");
59     return napi_create_int64(env, in, &out);
60 }
61 
62 /* napi_value <-> float */
GetValue(napi_env env,napi_value in,float & out)63 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, float &out)
64 {
65     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> float");
66     double tmp;
67     napi_status status = napi_get_value_double(env, in, &tmp);
68     out = tmp;
69     return status;
70 }
71 
SetValue(napi_env env,const float & in,napi_value & out)72 napi_status NapiDataUtils::SetValue(napi_env env, const float &in, napi_value &out)
73 {
74     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- float");
75     double tmp = in;
76     return napi_create_double(env, tmp, &out);
77 }
78 
79 /* napi_value <-> double */
GetValue(napi_env env,napi_value in,double & out)80 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, double &out)
81 {
82     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> double");
83     return napi_get_value_double(env, in, &out);
84 }
85 
SetValue(napi_env env,const double & in,napi_value & out)86 napi_status NapiDataUtils::SetValue(napi_env env, const double &in, napi_value &out)
87 {
88     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- double");
89     return napi_create_double(env, in, &out);
90 }
91 
92 /* napi_value <-> std::string */
GetValue(napi_env env,napi_value in,std::string & out)93 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::string &out)
94 {
95     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- string");
96     napi_valuetype type = napi_undefined;
97     napi_status status = napi_typeof(env, in, &type);
98     LOG_ERROR_RETURN((status == napi_ok) && (type == napi_string), "invalid type", napi_invalid_arg);
99 
100     size_t maxLen = STR_MAX_LENGTH;
101     status = napi_get_value_string_utf8(env, in, NULL, 0, &maxLen);
102     if (maxLen == 0) {
103         return status;
104     }
105     char *buf = new (std::nothrow) char[maxLen + STR_TAIL_LENGTH];
106     if (buf != nullptr) {
107         size_t len = 0;
108         status = napi_get_value_string_utf8(env, in, buf, maxLen + STR_TAIL_LENGTH, &len);
109         if (status == napi_ok) {
110             buf[len] = 0;
111             out = std::string(buf);
112         }
113         delete[] buf;
114     } else {
115         status = napi_generic_failure;
116     }
117     return status;
118 }
119 
SetValue(napi_env env,const std::string & in,napi_value & out)120 napi_status NapiDataUtils::SetValue(napi_env env, const std::string &in, napi_value &out)
121 {
122     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- std::string %{public}d", (int)in.length());
123     return napi_create_string_utf8(env, in.c_str(), in.size(), &out);
124 }
125 
126 /* napi_value <-> std::vector<std::string> */
GetValue(napi_env env,napi_value in,std::vector<std::string> & out)127 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::vector<std::string> &out)
128 {
129     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> std::vector<std::string>");
130     bool isArray = false;
131     napi_is_array(env, in, &isArray);
132     LOG_ERROR_RETURN(isArray, "not an array", napi_invalid_arg);
133 
134     uint32_t length = 0;
135     napi_status status = napi_get_array_length(env, in, &length);
136     LOG_ERROR_RETURN((status == napi_ok) && (length > 0), "get_array failed!", napi_invalid_arg);
137     for (uint32_t i = 0; i < length; ++i) {
138         napi_value item = nullptr;
139         status = napi_get_element(env, in, i, &item);
140         LOG_ERROR_RETURN((item != nullptr) && (status == napi_ok), "no element", napi_invalid_arg);
141         std::string value;
142         status = GetValue(env, item, value);
143         LOG_ERROR_RETURN(status == napi_ok, "not a string", napi_invalid_arg);
144         out.push_back(value);
145     }
146     return status;
147 }
148 
SetValue(napi_env env,const std::vector<std::string> & in,napi_value & out)149 napi_status NapiDataUtils::SetValue(napi_env env, const std::vector<std::string> &in, napi_value &out)
150 {
151     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- std::vector<std::string>");
152     napi_status status = napi_create_array_with_length(env, in.size(), &out);
153     LOG_ERROR_RETURN(status == napi_ok, "create array failed!", status);
154     int index = 0;
155     for (auto &item : in) {
156         napi_value element = nullptr;
157         SetValue(env, item, element);
158         status = napi_set_element(env, out, index++, element);
159         LOG_ERROR_RETURN((status == napi_ok), "napi_set_element failed!", status);
160     }
161     return status;
162 }
163 
164 /* napi_value <-> std::vector<uint8_t> */
GetValue(napi_env env,napi_value in,std::vector<uint8_t> & out)165 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::vector<uint8_t> &out)
166 {
167     out.clear();
168     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> std::vector<uint8_t> ");
169     napi_typedarray_type type = napi_biguint64_array;
170     size_t length = 0;
171     napi_value buffer = nullptr;
172     size_t offset = 0;
173     void *data = nullptr;
174     napi_status status = napi_get_typedarray_info(env, in, &type, &length, &data, &buffer, &offset);
175     LOG_DEBUG(UDMF_KITS_NAPI, "array type=%{public}d length=%{public}d offset=%{public}d  status=%{public}d",
176         (int)type, (int)length, (int)offset, status);
177     LOG_ERROR_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
178     LOG_ERROR_RETURN(type == napi_uint8_array, "is not Uint8Array!", napi_invalid_arg);
179     LOG_ERROR_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
180     out.assign(reinterpret_cast<uint8_t *>(data), reinterpret_cast<uint8_t *>(data) + length);
181     return status;
182 }
183 
SetValue(napi_env env,const std::vector<uint8_t> & in,napi_value & out)184 napi_status NapiDataUtils::SetValue(napi_env env, const std::vector<uint8_t> &in, napi_value &out)
185 {
186     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- std::vector<uint8_t> ");
187     LOG_ERROR_RETURN(in.size() > 0, "invalid std::vector<uint8_t>", napi_invalid_arg);
188     void *data = nullptr;
189     napi_value buffer = nullptr;
190     napi_status status = napi_create_arraybuffer(env, in.size(), &data, &buffer);
191     LOG_ERROR_RETURN((status == napi_ok), "create array buffer failed!", status);
192 
193     if (memcpy_s(data, in.size(), in.data(), in.size()) != EOK) {
194         LOG_ERROR(UDMF_KITS_NAPI, "memcpy_s not EOK");
195         return napi_invalid_arg;
196     }
197     status = napi_create_typedarray(env, napi_uint8_array, in.size(), buffer, 0, &out);
198     LOG_ERROR_RETURN((status == napi_ok), "napi_value <- std::vector<uint8_t> invalid value", status);
199     return status;
200 }
201 
202 /* napi_value <-> std::map<std::string, int32_t> */
GetValue(napi_env env,napi_value in,std::map<std::string,int32_t> & out)203 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::map<std::string, int32_t> &out)
204 {
205     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> std::map<std::string, int32_t> ");
206     (void)(env);
207     (void)(in);
208     (void)(out);
209     LOG_ERROR_RETURN(false, "std::map<std::string, uint32_t> from napi_value, unsupported!", napi_invalid_arg);
210     return napi_invalid_arg;
211 }
212 
SetValue(napi_env env,const std::map<std::string,int32_t> & in,napi_value & out)213 napi_status NapiDataUtils::SetValue(napi_env env, const std::map<std::string, int32_t> &in, napi_value &out)
214 {
215     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- std::map<std::string, int32_t> ");
216     napi_status status = napi_create_array_with_length(env, in.size(), &out);
217     LOG_ERROR_RETURN((status == napi_ok), "invalid object", status);
218     int index = 0;
219     for (const auto &[key, value] : in) {
220         napi_value element = nullptr;
221         napi_create_array_with_length(env, TUPLE_SIZE, &element);
222         napi_value jsKey = nullptr;
223         napi_create_string_utf8(env, key.c_str(), key.size(), &jsKey);
224         napi_set_element(env, element, TUPLE_KEY, jsKey);
225         napi_value jsValue = nullptr;
226         napi_create_int32(env, static_cast<int32_t>(value), &jsValue);
227         napi_set_element(env, element, TUPLE_VALUE, jsValue);
228         napi_set_element(env, out, index++, element);
229     }
230     return status;
231 }
232 
233 /* napi_value <-> std::map<std::string, int64_t> */
GetValue(napi_env env,napi_value in,std::map<std::string,int64_t> & out)234 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::map<std::string, int64_t> &out)
235 {
236     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> std::map<std::string, int64_t> ");
237     (void)(env);
238     (void)(in);
239     (void)(out);
240     LOG_ERROR_RETURN(false, "std::map<std::string, int64_t> from napi_value, unsupported!", napi_invalid_arg);
241     return napi_invalid_arg;
242 }
243 
SetValue(napi_env env,const std::map<std::string,int64_t> & in,napi_value & out)244 napi_status NapiDataUtils::SetValue(napi_env env, const std::map<std::string, int64_t> &in, napi_value &out)
245 {
246     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- std::map<std::string, int64_t> ");
247     napi_status status = napi_create_array_with_length(env, in.size(), &out);
248     LOG_ERROR_RETURN((status == napi_ok), "invalid object", status);
249     int index = 0;
250     for (const auto &[key, value] : in) {
251         napi_value element = nullptr;
252         napi_create_array_with_length(env, TUPLE_SIZE, &element);
253         napi_value jsKey = nullptr;
254         napi_create_string_utf8(env, key.c_str(), key.size(), &jsKey);
255         napi_set_element(env, element, TUPLE_KEY, jsKey);
256         napi_value jsValue = nullptr;
257         napi_create_int64(env, static_cast<int64_t>(value), &jsValue);
258         napi_set_element(env, element, TUPLE_VALUE, jsValue);
259         napi_set_element(env, out, index++, element);
260     }
261     return status;
262 }
263 
264 /* napi_value <-> UDVariant */
GetValue(napi_env env,napi_value in,UDVariant & out)265 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, UDVariant &out)
266 {
267     napi_valuetype type = napi_undefined;
268     napi_status status = napi_typeof(env, in, &type);
269     LOG_ERROR_RETURN((status == napi_ok), "invalid type", status);
270     switch (type) {
271         case napi_boolean: {
272             bool vBool = false;
273             status = GetValue(env, in, vBool);
274             out = vBool;
275             break;
276         }
277         case napi_number: {
278             double vNum = 0.0f;
279             status = GetValue(env, in, vNum);
280             out = vNum;
281             break;
282         }
283         case napi_string: {
284             std::string vString;
285             status = GetValue(env, in, vString);
286             out = vString;
287             break;
288         }
289         case napi_object: {
290             std::vector<uint8_t> vct;
291             status = GetValue(env, in, vct);
292             out = vct;
293             break;
294         }
295         default:
296             LOG_ERROR(UDMF_KITS_NAPI,
297                 "napi_value <- UDVariant not [Uint8Array | string | boolean | number] type=%{public}d", type);
298             status = napi_invalid_arg;
299             break;
300     }
301     return status;
302 }
303 
SetValue(napi_env env,const UDVariant & in,napi_value & out)304 napi_status NapiDataUtils::SetValue(napi_env env, const UDVariant &in, napi_value &out)
305 {
306     auto strValue = std::get_if<std::string>(&in);
307     if (strValue != nullptr) {
308         return SetValue(env, *strValue, out);
309     }
310     auto intValue = std::get_if<int32_t>(&in);
311     if (intValue != nullptr) {
312         return SetValue(env, *intValue, out);
313     }
314     auto pUint8 = std::get_if<std::vector<uint8_t>>(&in);
315     if (pUint8 != nullptr) {
316         return SetValue(env, *pUint8, out);
317     }
318     auto boolValue = std::get_if<bool>(&in);
319     if (boolValue != nullptr) {
320         return SetValue(env, *boolValue, out);
321     }
322     auto dblValue = std::get_if<double>(&in);
323     if (dblValue != nullptr) {
324         return SetValue(env, *dblValue, out);
325     }
326 
327     LOG_ERROR(UDMF_KITS_NAPI, "napi_value <- UDVariant  INVALID value type");
328     return napi_invalid_arg;
329 }
330 
331 /* napi_value <-> UDDetails */
GetValue(napi_env env,napi_value in,UDDetails & out)332 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, UDDetails &out)
333 {
334     if (!IsTypeForNapiValue(env, in, napi_object)) {
335         return napi_invalid_arg;
336     }
337     napi_value jsProNameList = nullptr;
338     uint32_t jsProCount = 0;
339 
340     NAPI_CALL_BASE(env, napi_get_property_names(env, in, &jsProNameList), napi_invalid_arg);
341     NAPI_CALL_BASE(env, napi_get_array_length(env, jsProNameList, &jsProCount), napi_invalid_arg);
342 
343     napi_value jsProName = nullptr;
344     napi_value jsProValue = nullptr;
345     for (uint32_t index = 0; index < jsProCount; index++) {
346         NAPI_CALL_BASE(env, napi_get_element(env, jsProNameList, index, &jsProName), napi_invalid_arg);
347         if (!IsTypeForNapiValue(env, jsProName, napi_string)) {
348             return napi_invalid_arg;
349         }
350         std::string strProName;
351         GetValue(env, jsProName, strProName);
352 
353         NAPI_CALL_BASE(env, napi_get_named_property(env, in, strProName.c_str(), &jsProValue), napi_invalid_arg);
354         UDVariant natValue;
355         GetValue(env, jsProValue, natValue);
356         out[strProName] = natValue;
357     }
358     return napi_ok;
359 }
360 
SetValue(napi_env env,const UDDetails & in,napi_value & out)361 napi_status NapiDataUtils::SetValue(napi_env env, const UDDetails &in, napi_value &out)
362 {
363     NAPI_CALL_BASE(env, napi_create_object(env, &out), napi_invalid_arg);
364     for (std::pair<std::string, UDVariant> prop : in) {
365         napi_value jsProValue = nullptr;
366         SetValue(env, prop.second, jsProValue);
367         NAPI_CALL_BASE(env, napi_set_named_property(env, out, prop.first.c_str(), jsProValue), napi_invalid_arg);
368     }
369     return napi_ok;
370 }
371 
GetValue(napi_env env,napi_value in,std::shared_ptr<TypeDescriptor> & descriptor)372 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::shared_ptr<TypeDescriptor> &descriptor)
373 {
374     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> std::GetValue TypeDescriptor");
375     napi_valuetype type = napi_undefined;
376     napi_status status = napi_typeof(env, in, &type);
377     LOG_ERROR_RETURN((status == napi_ok) && (type == napi_object), "invalid type", napi_invalid_arg);
378     TypeDescriptorNapi *descriptorNapi = nullptr;
379     napi_unwrap(env, in, reinterpret_cast<void **>(&descriptorNapi));
380     LOG_ERROR_RETURN((descriptorNapi != nullptr), "invalid type", napi_invalid_arg);
381     descriptor = descriptorNapi->value_;
382     if (descriptor == nullptr) {
383         LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> GetValue TypeDescriptor failed ");
384     }
385     return napi_ok;
386 }
387 
GetValue(napi_env env,napi_value in,std::shared_ptr<OHOS::Media::PixelMap> & pixelMap)388 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::shared_ptr<OHOS::Media::PixelMap> &pixelMap)
389 {
390     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> std::shared_ptr<OHOS::Media::PixelMap>");
391     pixelMap = OHOS::Media::PixelMapNapi::GetPixelMap(env, in);
392     return napi_ok;
393 }
394 
SetValue(napi_env env,const std::shared_ptr<OHOS::Media::PixelMap> & in,napi_value & out)395 napi_status NapiDataUtils::SetValue(napi_env env, const std::shared_ptr<OHOS::Media::PixelMap> &in, napi_value &out)
396 {
397     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- std::shared_ptr<OHOS::Media::PixelMap>");
398     out = OHOS::Media::PixelMapNapi::CreatePixelMap(env, in);
399     return napi_ok;
400 }
401 
GetValue(napi_env env,napi_value in,std::shared_ptr<OHOS::AAFwk::Want> & wantPtr)402 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::shared_ptr<OHOS::AAFwk::Want> &wantPtr)
403 {
404     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> std::shared_ptr<OHOS::AAFwk::Want>");
405     OHOS::AAFwk::Want want;
406     AppExecFwk::UnwrapWant(env, in, want);
407     wantPtr = std::make_shared<OHOS::AAFwk::Want>(want);
408     return napi_ok;
409 }
410 
SetValue(napi_env env,const std::shared_ptr<OHOS::AAFwk::Want> & in,napi_value & out)411 napi_status NapiDataUtils::SetValue(napi_env env, const std::shared_ptr<OHOS::AAFwk::Want> &in, napi_value &out)
412 {
413     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- std::shared_ptr<OHOS::AAFwk::Want>");
414     out = OHOS::AppExecFwk::WrapWant(env, *in);
415     return napi_ok;
416 }
417 
GetValue(napi_env env,napi_value in,std::shared_ptr<Object> & object)418 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::shared_ptr<Object> &object)
419 {
420     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> std::GetValue Object");
421     napi_value attributeNames = nullptr;
422     NAPI_CALL_BASE(env, napi_get_property_names(env, in, &attributeNames), napi_invalid_arg);
423     uint32_t attributesNum = 0;
424     NAPI_CALL_BASE(env, napi_get_array_length(env, attributeNames, &attributesNum), napi_invalid_arg);
425     for (uint32_t i = 0; i < attributesNum; i++) {
426         napi_value attributeNameNapi = nullptr;
427         NAPI_CALL_BASE(env, napi_get_element(env, attributeNames, i, &attributeNameNapi), napi_invalid_arg);
428         size_t len = 0;
429         char str[STR_MAX_SIZE] = { 0 };
430         NAPI_CALL_BASE(env, napi_get_value_string_utf8(
431             env, attributeNameNapi, str, STR_MAX_SIZE, &len), napi_invalid_arg);
432         std::string attributeName = str;
433         napi_value attributeValueNapi = nullptr;
434         NAPI_CALL_BASE(env, napi_get_named_property(env, in, str, &attributeValueNapi), napi_invalid_arg);
435 
436         bool isArrayBuffer = false;
437         NAPI_CALL_BASE(env, napi_is_arraybuffer(env, attributeValueNapi, &isArrayBuffer), napi_invalid_arg);
438         if (isArrayBuffer) {
439             void *data = nullptr;
440             size_t dataLen = 0;
441             NAPI_CALL_BASE(env, napi_get_arraybuffer_info(env, attributeValueNapi, &data, &dataLen), napi_invalid_arg);
442             object->value_[attributeName] = std::vector<uint8_t>(
443                 reinterpret_cast<uint8_t *>(data), reinterpret_cast<uint8_t *>(data) + dataLen);
444             continue;
445         }
446         napi_valuetype valueType = napi_undefined;
447         NAPI_CALL_BASE(env, napi_typeof(env, attributeValueNapi, &valueType), napi_invalid_arg);
448         switch (valueType) {
449             case napi_valuetype::napi_object:
450                 object->value_[attributeName] = std::make_shared<Object>();
451                 break;
452             case napi_valuetype::napi_number:
453                 object->value_[attributeName] = double();
454                 break;
455             case napi_valuetype::napi_string:
456                 object->value_[attributeName] = std::string();
457                 break;
458             case napi_valuetype::napi_boolean:
459                 object->value_[attributeName] = bool();
460                 break;
461             case napi_valuetype::napi_undefined:
462                 object->value_[attributeName] = std::monostate();
463                 break;
464             case napi_valuetype::napi_null:
465                 object->value_[attributeName] = nullptr;
466                 break;
467             default:
468                 return napi_invalid_arg;
469         }
470         napi_status status = napi_ok;
471         std::visit([&](auto &value) {status = NapiDataUtils::GetValue(env, attributeValueNapi, value);},
472             object->value_[attributeName]);
473         if (status != napi_ok) {
474             return status;
475         }
476     }
477     return napi_ok;
478 }
479 
SetValue(napi_env env,const std::shared_ptr<Object> & object,napi_value & out)480 napi_status NapiDataUtils::SetValue(napi_env env, const std::shared_ptr<Object> &object, napi_value &out)
481 {
482     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> std::GetValue Object");
483     napi_create_object(env, &out);
484     for (auto &[key, value] : object->value_) {
485         napi_value valueNapi = nullptr;
486         if (std::holds_alternative<std::vector<uint8_t>>(value)) {
487             auto array = std::get<std::vector<uint8_t>>(value);
488             void *data = nullptr;
489             size_t len = array.size();
490             NAPI_CALL_BASE(env, napi_create_arraybuffer(env, len, &data, &valueNapi), napi_generic_failure);
491             if (memcpy_s(data, len, reinterpret_cast<const void *>(array.data()), len) != 0) {
492                 LOG_ERROR(UDMF_KITS_NAPI, "memcpy_s failed");
493                 return napi_generic_failure;
494             }
495         } else {
496             std::visit([&](const auto &value) {NapiDataUtils::SetValue(env, value, valueNapi);}, value);
497         }
498         napi_set_named_property(env, out, key.c_str(), valueNapi);
499     }
500     return napi_ok;
501 }
502 
GetValue(napi_env env,napi_value in,std::monostate & out)503 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::monostate &out)
504 {
505     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> std::monostate");
506     out = std::monostate{};
507     return napi_ok;
508 }
509 
SetValue(napi_env env,const std::monostate & in,napi_value & out)510 napi_status NapiDataUtils::SetValue(napi_env env, const std::monostate &in, napi_value &out)
511 {
512     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- std::monostate");
513     return napi_get_undefined(env, &out);
514 }
515 
GetValue(napi_env env,napi_value in,nullptr_t & out)516 napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, nullptr_t &out)
517 {
518     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> null");
519     out = nullptr;
520     return napi_ok;
521 }
522 
SetValue(napi_env env,const nullptr_t & in,napi_value & out)523 napi_status NapiDataUtils::SetValue(napi_env env, const nullptr_t &in, napi_value &out)
524 {
525     LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- null");
526     return napi_get_null(env, &out);
527 }
528 
IsTypeForNapiValue(napi_env env,napi_value param,napi_valuetype expectType)529 bool NapiDataUtils::IsTypeForNapiValue(napi_env env, napi_value param, napi_valuetype expectType)
530 {
531     napi_valuetype valueType = napi_undefined;
532 
533     if (param == nullptr) {
534         return false;
535     }
536 
537     if (napi_typeof(env, param, &valueType) != napi_ok) {
538         return false;
539     }
540 
541     return valueType == expectType;
542 }
543 
IsNull(napi_env env,napi_value value)544 bool NapiDataUtils::IsNull(napi_env env, napi_value value)
545 {
546     napi_valuetype type = napi_undefined;
547     napi_status status = napi_typeof(env, value, &type);
548     if (status == napi_ok && (type == napi_undefined || type == napi_null)) {
549         return true;
550     }
551     if (type == napi_string) {
552         size_t len;
553         napi_get_value_string_utf8(env, value, NULL, 0, &len);
554         return len == 0;
555     }
556     return false;
557 }
558 
DefineClass(napi_env env,const std::string & name,const napi_property_descriptor * properties,size_t count,napi_callback newcb)559 napi_value NapiDataUtils::DefineClass(napi_env env, const std::string &name,
560     const napi_property_descriptor *properties, size_t count, napi_callback newcb)
561 {
562     // base64("data.udmf") as rootPropName, i.e. global.<root>
563     constexpr const char *rootPropName = "ZGF0YS51ZG1m";
564     napi_value root = nullptr;
565     bool hasRoot = false;
566     napi_value global = nullptr;
567     napi_get_global(env, &global);
568     napi_has_named_property(env, global, rootPropName, &hasRoot);
569     if (hasRoot) {
570         napi_get_named_property(env, global, rootPropName, &root);
571     } else {
572         napi_create_object(env, &root);
573         napi_set_named_property(env, global, rootPropName, root);
574     }
575 
576     std::string propName = "constructor_of_" + name;
577     napi_value constructor = nullptr;
578     bool hasProp = false;
579     napi_has_named_property(env, root, propName.c_str(), &hasProp);
580     if (hasProp) {
581         napi_get_named_property(env, root, propName.c_str(), &constructor);
582         if (constructor != nullptr) {
583             LOG_DEBUG(UDMF_KITS_NAPI, "got data.distributeddata.%{public}s as constructor", propName.c_str());
584             return constructor;
585         }
586         hasProp = false; // no constructor.
587     }
588 
589     NAPI_CALL_BASE(env,
590         napi_define_class(env, name.c_str(), name.size(), newcb, nullptr, count, properties, &constructor),
591         nullptr);
592     NAPI_ASSERT(env, constructor != nullptr, "napi_define_class failed!");
593 
594     if (!hasProp) {
595         napi_set_named_property(env, root, propName.c_str(), constructor);
596         LOG_DEBUG(UDMF_KITS_NAPI, "save constructor to data.distributeddata.%{public}s", propName.c_str());
597     }
598     return constructor;
599 }
600 } // namespace UDMF
601 } // namespace OHOS
602