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