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