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 
16 #include "napi_util.h"
17 #include <endian.h>
18 #include <securec.h>
19 #include <sstream>
20 #include "calendar_log.h"
21 #include "napi_queue.h"
22 #include "native_util.h"
23 #include "event_filter_napi.h"
24 #include <climits>
25 
26 namespace OHOS::CalendarApi::NapiUtil {
27 constexpr int32_t STR_MAX_LENGTH = 4096;
28 constexpr size_t STR_TAIL_LENGTH = 1;
29 
GetValue(napi_env env, napi_value in, napi_value& out)30 napi_status GetValue(napi_env env, napi_value in, napi_value& out)
31 {
32     out = in;
33     return napi_ok;
34 }
35 
SetValue(napi_env env, napi_value in, napi_value& out)36 napi_status SetValue(napi_env env, napi_value in, napi_value& out)
37 {
38     out = in;
39     return napi_ok;
40 }
41 
42 /* napi_value <-> bool */
GetValue(napi_env env, napi_value in, bool& out)43 napi_status GetValue(napi_env env, napi_value in, bool& out)
44 {
45     return napi_get_value_bool(env, in, &out);
46 }
47 
SetValue(napi_env env, const bool& in, napi_value& out)48 napi_status SetValue(napi_env env, const bool& in, napi_value& out)
49 {
50     return napi_get_boolean(env, in, &out);
51 }
52 
53 /* napi_value <-> int32_t */
GetValue(napi_env env, napi_value in, int32_t& out)54 napi_status GetValue(napi_env env, napi_value in, int32_t& out)
55 {
56     return napi_get_value_int32(env, in, &out);
57 }
58 
SetValue(napi_env env, const int32_t& in, napi_value& out)59 napi_status SetValue(napi_env env, const int32_t& in, napi_value& out)
60 {
61     return napi_create_int32(env, in, &out);
62 }
63 
64 /* napi_value <-> uint32_t */
GetValue(napi_env env, napi_value in, uint32_t& out)65 napi_status GetValue(napi_env env, napi_value in, uint32_t& out)
66 {
67     return napi_get_value_uint32(env, in, &out);
68 }
69 
SetValue(napi_env env, const uint32_t& in, napi_value& out)70 napi_status SetValue(napi_env env, const uint32_t& in, napi_value& out)
71 {
72     return napi_create_uint32(env, in, &out);
73 }
74 
75 /* napi_value <-> int64_t */
GetValue(napi_env env, napi_value in, int64_t& out)76 napi_status GetValue(napi_env env, napi_value in, int64_t& out)
77 {
78     return napi_get_value_int64(env, in, &out);
79 }
80 
SetValue(napi_env env, const int64_t& in, napi_value& out)81 napi_status SetValue(napi_env env, const int64_t& in, napi_value& out)
82 {
83     return napi_create_int64(env, in, &out);
84 }
85 
GetValue(napi_env env, napi_value in, uint64_t& out)86 napi_status GetValue(napi_env env, napi_value in, uint64_t& out)
87 {
88     bool lossless = true;
89     return napi_get_value_bigint_uint64(env, in, &out, &lossless);
90 }
91 
SetValue(napi_env env, const uint64_t& in, napi_value& out)92 napi_status SetValue(napi_env env, const uint64_t& in, napi_value& out)
93 {
94     return napi_create_bigint_uint64(env, in, &out);
95 }
96 
97 /* napi_value <-> double */
GetValue(napi_env env, napi_value in, double& out)98 napi_status GetValue(napi_env env, napi_value in, double& out)
99 {
100     return napi_get_value_double(env, in, &out);
101 }
102 
SetValue(napi_env env, const double& in, napi_value& out)103 napi_status SetValue(napi_env env, const double& in, napi_value& out)
104 {
105     return napi_create_double(env, in, &out);
106 }
107 
108 /* napi_value <-> std::string */
GetValue(napi_env env, napi_value in, std::string& out)109 napi_status GetValue(napi_env env, napi_value in, std::string& out)
110 {
111     napi_valuetype type = napi_undefined;
112     napi_status status = napi_typeof(env, in, &type);
113     CHECK_RETURN((status == napi_ok) && (type == napi_string), "invalid type", napi_invalid_arg);
114 
115     size_t maxLen = STR_MAX_LENGTH;
116     status = napi_get_value_string_utf8(env, in, NULL, 0, &maxLen);
117     if (maxLen == 0 || maxLen == UINT_MAX) {
118         return status;
119     }
120     LOG_DEBUG("napi_value -> std::string get length %{public}d", (int)maxLen);
121     char* buf = new (std::nothrow) char[STR_TAIL_LENGTH + maxLen];
122     if (buf != nullptr) {
123         size_t len = 0;
124         status = napi_get_value_string_utf8(env, in, buf, STR_TAIL_LENGTH + maxLen, &len);
125         if (status == napi_ok) {
126             buf[len] = 0;
127             out = std::string(buf);
128         }
129         delete[] buf;
130     } else {
131         status = napi_generic_failure;
132     }
133     return status;
134 }
135 
SetValue(napi_env env, const std::string& in, napi_value& out)136 napi_status SetValue(napi_env env, const std::string& in, napi_value& out)
137 {
138     return napi_create_string_utf8(env, in.c_str(), in.size(), &out);
139 }
140 
141 /* napi_value <-> std::vector<std::string> */
GetValue(napi_env env, napi_value in, std::vector<std::string>& out)142 napi_status GetValue(napi_env env, napi_value in, std::vector<std::string>& out)
143 {
144     LOG_DEBUG("napi_value -> std::vector<std::string>");
145     return GetValueArray(env, in, out);
146 }
147 
SetValue(napi_env env, const std::vector<std::string>& in, napi_value& out)148 napi_status SetValue(napi_env env, const std::vector<std::string>& in, napi_value& out)
149 {
150     LOG_DEBUG("std::vector<std::string> -> napi_value");
151     napi_status status = napi_create_array_with_length(env, in.size(), &out);
152     CHECK_RETURN(status == napi_ok, "create array failed!", status);
153     int index = 0;
154     for (auto& item : in) {
155         napi_value element = nullptr;
156         SetValue(env, item, element);
157         status = napi_set_element(env, out, index++, element);
158         CHECK_RETURN((status == napi_ok), "napi_set_element failed!", status);
159     }
160     return status;
161 }
162 
163 /* napi_value <-> std::vector<uint8_t> */
GetValue(napi_env env, napi_value in, std::vector<uint8_t>& out)164 napi_status GetValue(napi_env env, napi_value in, std::vector<uint8_t>& out)
165 {
166     out.clear();
167     LOG_DEBUG("napi_value -> std::vector<uint8_t> ");
168     napi_typedarray_type type = napi_biguint64_array;
169     size_t length = 0;
170     napi_value buffer = nullptr;
171     size_t offset = 0;
172     void* data = nullptr;
173     napi_status status = napi_get_typedarray_info(env, in, &type, &length, &data, &buffer, &offset);
174     LOG_DEBUG("array type=%{public}d length=%{public}d offset=%{public}d", (int)type, (int)length, (int)offset);
175     CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
176     CHECK_RETURN(type == napi_uint8_array, "is not Uint8Array!", napi_invalid_arg);
177     CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
178     out.assign((uint8_t*)data, ((uint8_t*)data) + length);
179     return status;
180 }
181 
SetValue(napi_env env, const std::vector<uint8_t>& in, napi_value& out)182 napi_status SetValue(napi_env env, const std::vector<uint8_t>& in, napi_value& out)
183 {
184     LOG_DEBUG("napi_value <- std::vector<uint8_t> ");
185     CHECK_RETURN(in.size() > 0, "invalid std::vector<uint8_t>", napi_invalid_arg);
186     void* data = nullptr;
187     napi_value buffer = nullptr;
188     napi_status status = napi_create_arraybuffer(env, in.size(), &data, &buffer);
189     CHECK_RETURN((status == napi_ok), "create array buffer failed!", status);
190 
191     if (memcpy_s(data, in.size(), in.data(), in.size()) != EOK) {
192         LOG_ERROR("memcpy_s not EOK");
193         return napi_invalid_arg;
194     }
195     status = napi_create_typedarray(env, napi_uint8_array, in.size(), buffer, 0, &out);
196     CHECK_RETURN((status == napi_ok), "napi_value <- std::vector<uint8_t> invalid value", status);
197     return status;
198 }
199 
200 /* napi_value <-> std::vector<int32_t> */
GetValue(napi_env env, napi_value in, std::vector<int32_t>& out)201 napi_status GetValue(napi_env env, napi_value in, std::vector<int32_t>& out)
202 {
203     LOG_DEBUG("napi_value -> std::vector<int32_t> ");
204     return GetValueArray(env, in, out);
205 }
206 
SetValue(napi_env env, const std::vector<int32_t>& in, napi_value& out)207 napi_status SetValue(napi_env env, const std::vector<int32_t>& in, napi_value& out)
208 {
209     LOG_DEBUG("napi_value <- std::vector<int32_t> ");
210     return SetValueArray(env, in, out);
211 }
212 
213 /* napi_value <-> std::vector<uint32_t> */
GetValue(napi_env env, napi_value in, std::vector<uint32_t>& out)214 napi_status GetValue(napi_env env, napi_value in, std::vector<uint32_t>& out)
215 {
216     LOG_DEBUG("napi_value -> std::vector<uint32_t> ");
217     return GetValueArray(env, in, out);
218 }
219 
SetValue(napi_env env, const std::vector<uint32_t>& in, napi_value& out)220 napi_status SetValue(napi_env env, const std::vector<uint32_t>& in, napi_value& out)
221 {
222     LOG_DEBUG("napi_value <- std::vector<uint32_t> ");
223     size_t bytes = in.size() * sizeof(uint32_t);
224     CHECK_RETURN(bytes > 0, "invalid std::vector<uint32_t>", napi_invalid_arg);
225     void* data = nullptr;
226     napi_value buffer = nullptr;
227     napi_status status = napi_create_arraybuffer(env, bytes, &data, &buffer);
228     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
229 
230     if (memcpy_s(data, bytes, in.data(), bytes) != EOK) {
231         LOG_ERROR("memcpy_s not EOK");
232         return napi_invalid_arg;
233     }
234     status = napi_create_typedarray(env, napi_uint32_array, in.size(), buffer, 0, &out);
235     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
236     return status;
237 }
238 
239 /* napi_value <-> std::vector<int64_t> */
GetValue(napi_env env, napi_value in, std::vector<int64_t>& out)240 napi_status GetValue(napi_env env, napi_value in, std::vector<int64_t>& out)
241 {
242     LOG_DEBUG("napi_value -> std::vector<int64_t> ");
243     return GetValueArray(env, in, out);
244 }
245 
SetValue(napi_env env, const std::vector<int64_t>& in, napi_value& out)246 napi_status SetValue(napi_env env, const std::vector<int64_t>& in, napi_value& out)
247 {
248     LOG_DEBUG("napi_value <- std::vector<int64_t> ");
249     size_t bytes = in.size() * sizeof(int64_t);
250     CHECK_RETURN(bytes > 0, "invalid std::vector<uint32_t>", napi_invalid_arg);
251     void* data = nullptr;
252     napi_value buffer = nullptr;
253     napi_status status = napi_create_arraybuffer(env, bytes, &data, &buffer);
254     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
255     if (!in.data()) {
256         return napi_invalid_arg;
257     }
258     if (memcpy_s(data, bytes, in.data(), bytes) != EOK) {
259         LOG_ERROR("memcpy_s not EOK");
260         return napi_invalid_arg;
261     }
262     status = napi_create_typedarray(env, napi_bigint64_array, in.size(), buffer, 0, &out);
263     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
264     return status;
265 }
266 
GetValue(napi_env env, napi_value in, CalendarAccount& out)267 napi_status GetValue(napi_env env, napi_value in, CalendarAccount& out)
268 {
269     LOG_DEBUG("napi_value -> CalendarAccount ");
270     napi_status status = NapiUtil::GetNamedProperty(env, in, "name", out.name);
271     CHECK_RETURN((status == napi_ok), "invalid name", status);
272     status = NapiUtil::GetNamedProperty(env, in, "type", out.type);
273     CHECK_RETURN((status == napi_ok), "invalid type", status);
274     NapiUtil::GetNamedPropertyOptional(env, in, "displayName", out.displayName);
275     return napi_ok;
276 }
277 
SetValue(napi_env env, const CalendarAccount& in, napi_value& out)278 napi_status SetValue(napi_env env, const CalendarAccount& in, napi_value& out)
279 {
280     LOG_DEBUG("CalendarAccount -> napi_value ");
281     napi_status status = napi_create_object(env, &out);
282     CHECK_RETURN((status == napi_ok), "invalid entry object", status);
283 
284     napi_value nameValue = nullptr;
285     status = SetValue(env, in.name, nameValue);
286     CHECK_RETURN((status == napi_ok), "invalid entry name", status);
287     napi_set_named_property(env, out, "name", nameValue);
288     napi_value typeValue = nullptr;
289     status = SetValue(env, in.type, typeValue);
290     CHECK_RETURN((status == napi_ok), "invalid entry type", status);
291     napi_set_named_property(env, out, "type", typeValue);
292 
293     if (in.displayName) {
294         napi_value displayNameValue = nullptr;
295         status = SetValue(env, in.displayName.value(), displayNameValue);
296         CHECK_RETURN((status == napi_ok), "invalid entry displayName", status);
297         napi_set_named_property(env, out, "displayName", displayNameValue);
298     }
299     return status;
300 }
301 
302 /* napi_value <-> CalendarConfig */
GetValue(napi_env env, napi_value in, CalendarConfig& out)303 napi_status GetValue(napi_env env, napi_value in, CalendarConfig& out)
304 {
305     LOG_DEBUG("napi_value -> CalendarConfig ");
306     NapiUtil::GetNamedPropertyOptional(env, in, "enableReminder", out.enableReminder);
307     bool result = true;
308     napi_status status = napi_has_named_property(env, in, "color", &result);
309     if (status == napi_ok && !result) {
310         const int64_t defaultColor = 0xFF0A59F7;
311         LOG_DEBUG("napi_value color is null, use default color: 0xFF0A59F7");
312         out.color.emplace<1>(defaultColor);
313         return napi_ok;
314     }
315     napi_value value = NULL;
316     napi_valuetype valueType = napi_undefined;
317     napi_get_named_property(env, in, "color", &value);
318     napi_typeof(env, value, &valueType);
319     if (valueType == napi_string) {
320         LOG_DEBUG("napi_value color is string");
321         string str = "";
322         NapiUtil::GetValue(env, value, str);
323         LOG_DEBUG("napi_value color: %{public}s", str.c_str());
324         bool ok = Native::ColorParse(str, out.color);
325         if (!ok) {
326             return napi_string_expected;
327         }
328         return napi_ok;
329     }
330     LOG_DEBUG("napi_value color is number");
331     int64_t colorValue;
332     napi_status statusToGetInt64 = napi_get_value_int64(env, value, &colorValue);
333     if (statusToGetInt64 == napi_ok) {
334         out.color.emplace<1>(colorValue);
335         LOG_DEBUG("color: %{public}s", std::to_string(std::get<1>(out.color)).c_str());
336     } else {
337         LOG_DEBUG("color number -> int_64 err");
338     }
339     return statusToGetInt64;
340 }
341 
SetValue(napi_env env, const CalendarConfig& in, napi_value& out)342 napi_status SetValue(napi_env env, const CalendarConfig& in, napi_value& out)
343 {
344     LOG_DEBUG("CalendarConfig -> napi_value ");
345     napi_status status = napi_create_object(env, &out);
346     CHECK_RETURN((status == napi_ok), "invalid entry object", status);
347 
348     if (in.enableReminder.has_value()) {
349         LOG_DEBUG("config.enableReminder: %{public}d", in.enableReminder.value_or(-1));
350         napi_value enableRemindValue = nullptr;
351         status = SetValue(env, in.enableReminder.value(), enableRemindValue);
352         CHECK_RETURN((status == napi_ok), "invalid entry enableReminder", status);
353         napi_set_named_property(env, out, "enableReminder", enableRemindValue);
354     }
355     if (std::get_if<1>(&in.color)) {
356         napi_value colorValue = nullptr;
357         string color;
358         std::stringstream ss;
359         ss << std::hex << std::uppercase << std::get<1>(in.color);
360         ss >> color;
361         const int rgbLen = 5;
362         const int argbLen = 7;
363         if (color.size() == rgbLen || color.size() == argbLen) {
364             color = '0' + color;
365         }
366         color = '#' + color;
367         LOG_DEBUG("config.color: %{public}s", color.c_str());
368         status = SetValue(env, color, colorValue);
369         CHECK_RETURN((status == napi_ok), "invalid entry color", status);
370         napi_set_named_property(env, out, "color", colorValue);
371     }
372     return status;
373 }
374 
GetValue(napi_env env, napi_value in, Location& out)375 napi_status GetValue(napi_env env, napi_value in, Location& out)
376 {
377     LOG_DEBUG("napi_value -> Location ");
378     NapiUtil::GetNamedPropertyOptional(env, in, "location", out.location);
379     NapiUtil::GetNamedPropertyOptional(env, in, "longitude", out.longitude);
380     NapiUtil::GetNamedPropertyOptional(env, in, "latitude", out.latitude);
381     return napi_ok;
382 }
383 
SetValue(napi_env env, const Location& in, napi_value& out)384 napi_status SetValue(napi_env env, const Location& in, napi_value& out)
385 {
386     LOG_DEBUG("Location -> napi_value ");
387     napi_status status = napi_create_object(env, &out);
388     CHECK_RETURN((status == napi_ok), "invalid entry object", status);
389 
390     if (in.location) {
391         napi_value locationValue = nullptr;
392         status = SetValue(env, in.location.value(), locationValue);
393         CHECK_RETURN((status == napi_ok), "invalid location", status);
394         napi_set_named_property(env, out, "location", locationValue);
395     }
396     if (in.longitude) {
397         napi_value value = nullptr;
398         status = SetValue(env, in.longitude.value(), value);
399         CHECK_RETURN((status == napi_ok), "invalid longitude", status);
400         napi_set_named_property(env, out, "longitude", value);
401     }
402     if (in.latitude) {
403         napi_value value = nullptr;
404         status = SetValue(env, in.latitude.value(), value);
405         CHECK_RETURN((status == napi_ok), "invalid latitude", status);
406         napi_set_named_property(env, out, "latitude", value);
407     }
408     return napi_ok;
409 }
410 
411 /* napi_value <-> RecurrenceRule */
GetValue(napi_env env, napi_value in, RecurrenceRule& out)412 napi_status GetValue(napi_env env, napi_value in, RecurrenceRule& out)
413 {
414     LOG_DEBUG("napi_value -> RecurrenceRule ");
415     int recurrence = -1;
416     NapiUtil::GetNamedProperty(env, in, "recurrenceFrequency", recurrence);
417     out.recurrenceFrequency = static_cast<RecurrenceType>(recurrence);
418     NapiUtil::GetNamedPropertyOptional(env, in, "expire", out.expire);
419     NapiUtil::GetNamedPropertyOptional(env, in, "count", out.count);
420     NapiUtil::GetNamedPropertyOptional(env, in, "interval", out.interval);
421     NapiUtil::GetNamedPropertyOptional(env, in, "excludedDates", out.excludedDates);
422     NapiUtil::GetNamedPropertyOptional(env, in, "daysOfWeek", out.daysOfWeek);
423     NapiUtil::GetNamedPropertyOptional(env, in, "daysOfMonth", out.daysOfMonth);
424     NapiUtil::GetNamedPropertyOptional(env, in, "daysOfYear", out.daysOfYear);
425     NapiUtil::GetNamedPropertyOptional(env, in, "weeksOfMonth", out.weeksOfMonth);
426     NapiUtil::GetNamedPropertyOptional(env, in, "weeksOfYear", out.weeksOfYear);
427     NapiUtil::GetNamedPropertyOptional(env, in, "monthsOfYear", out.monthsOfYear);
428     return napi_ok;
429 }
430 
SetValue(napi_env env, const RecurrenceRule& in, napi_value& out)431 napi_status SetValue(napi_env env, const RecurrenceRule& in, napi_value& out)
432 {
433     LOG_DEBUG("RecurrenceRule -> napi_value ");
434     napi_status status = napi_create_object(env, &out);
435     CHECK_RETURN((status == napi_ok), "invalid recurrenceRule", status);
436     status = SetNamedProperty(env, "recurrenceFrequency", in.recurrenceFrequency, out);
437     CHECK_RETURN((status == napi_ok), "invalid recurrenceFrequency", status);
438     SetNamedPropertyOptional(env, "expire", in.expire, out);
439     SetNamedPropertyOptional(env, "count", in.count, out);
440     SetNamedPropertyOptional(env, "interval", in.interval, out);
441     SetNamedPropertyOptional(env, "excludedDates", in.excludedDates, out);
442     SetNamedPropertyOptional(env, "daysOfWeek", in.daysOfWeek, out);
443     SetNamedPropertyOptional(env, "daysOfMonth", in.daysOfMonth, out);
444     SetNamedPropertyOptional(env, "daysOfYear", in.daysOfYear, out);
445     SetNamedPropertyOptional(env, "weeksOfMonth", in.weeksOfMonth, out);
446     SetNamedPropertyOptional(env, "weeksOfYear", in.weeksOfYear, out);
447     SetNamedPropertyOptional(env, "monthsOfYear", in.monthsOfYear, out);
448     return napi_ok;
449 }
450 
451 /* napi_value <-> Attendee */
GetValue(napi_env env, napi_value in, Attendee& out)452 napi_status GetValue(napi_env env, napi_value in, Attendee& out)
453 {
454     LOG_DEBUG("Attendee -> napi_value ");
455     NapiUtil::GetNamedProperty(env, in, "name", out.name);
456     NapiUtil::GetNamedProperty(env, in, "email", out.email);
457     optional<std::string> value;
458     NapiUtil::GetNamedPropertyOptional(env, in, "role", value);
459     if (!value.has_value()) {
460         return napi_ok;
461     }
462 
463     if (value == "organizer") {
464         out.role = ORGANIZER;
465     } else {
466         out.role = PARTICIPANT;
467     }
468     return napi_ok;
469 }
470 
SetValue(napi_env env, const Attendee& in, napi_value& out)471 napi_status SetValue(napi_env env, const Attendee& in, napi_value& out)
472 {
473     LOG_DEBUG("napi_value -> Attendee ");
474     napi_status status = napi_create_object(env, &out);
475     CHECK_RETURN((status == napi_ok), "invalid entry object", status);
476 
477     napi_value nameValue = nullptr;
478     status = SetValue(env, in.name, nameValue);
479     CHECK_RETURN((status == napi_ok), "invalid entry name", status);
480     napi_set_named_property(env, out, "name", nameValue);
481     napi_value emailValue = nullptr;
482     status = SetValue(env, in.email, emailValue);
483     CHECK_RETURN((status == napi_ok), "invalid entry type", status);
484     napi_set_named_property(env, out, "email", emailValue);
485     if (!in.role.has_value()) {
486         return napi_ok;
487     }
488     std::string value;
489     if (in.role == PARTICIPANT) {
490         value = "organizer";
491     } else {
492         value = "participant";
493     }
494     napi_value roleValue = nullptr;
495     status = SetValue(env, value, roleValue);
496     CHECK_RETURN((status == napi_ok), "invalid role", status);
497     napi_set_named_property(env, out, "role", roleValue);
498     return napi_ok;
499 }
500 
501 /* napi_value <-> std::vector<Attendee> */
GetValue(napi_env env, napi_value in, std::vector<Attendee>& out)502 napi_status GetValue(napi_env env, napi_value in, std::vector<Attendee>& out)
503 {
504     LOG_DEBUG("napi_value -> std::vector<Attendee> ");
505     return GetValueArray(env, in, out);
506 }
507 
SetValue(napi_env env, const std::vector<Attendee>& in, napi_value& out)508 napi_status SetValue(napi_env env, const std::vector<Attendee>& in, napi_value& out)
509 {
510     LOG_DEBUG("std::vector<Attendee> -> napi_value ");
511     return SetValueArray(env, in, out);
512 }
513 
GetValue(napi_env env, napi_value in, EventService& out)514 napi_status GetValue(napi_env env, napi_value in, EventService& out)
515 {
516     LOG_DEBUG("napi_value -> EventService");
517     NapiUtil::GetNamedPropertyOptional(env, in, "description", out.description);
518     NapiUtil::GetNamedProperty(env, in, "type", out.type);
519     return NapiUtil::GetNamedProperty(env, in, "uri", out.uri);
520 }
521 
SetValue(napi_env env, const EventService& in, napi_value& out)522 napi_status SetValue(napi_env env, const EventService& in, napi_value& out)
523 {
524     LOG_DEBUG("EventService -> napi_value");
525     napi_status status = napi_create_object(env, &out);
526     CHECK_RETURN((status == napi_ok), "invalid entry object", status);
527 
528     napi_value typeValue = nullptr;
529     status = SetValue(env, in.type, typeValue);
530     CHECK_RETURN((status == napi_ok), "invalid typeValue", status);
531     status = napi_set_named_property(env, out, "type", typeValue);
532     CHECK_RETURN((status == napi_ok), "set type failed", status);
533 
534     napi_value uriValue = nullptr;
535     status = SetValue(env, in.uri, uriValue);
536     CHECK_RETURN((status == napi_ok), "invalid entry type", status);
537     status = napi_set_named_property(env, out, "uri", uriValue);
538     CHECK_RETURN((status == napi_ok), "set uri failed", status);
539 
540     if (in.description) {
541         napi_value descriptionValue = nullptr;
542         status = SetValue(env, in.description.value(), descriptionValue);
543         CHECK_RETURN((status == napi_ok), "invalid description", status);
544         status = napi_set_named_property(env, out, "description", descriptionValue);
545         CHECK_RETURN((status == napi_ok), "set description failed", status);
546     }
547     return status;
548 }
549 
550 /* napi_value <-> EventFilter */
GetValue(napi_env env, napi_value in, EventFilterNapi*& out)551 napi_status GetValue(napi_env env, napi_value in, EventFilterNapi*& out)
552 {
553     LOG_DEBUG("napi_value -> EventFilter ");
554     return EventFilterNapi::ToJson(env, in, out);
555 }
556 
SetValue(napi_env env, const EventFilterNapi& in, napi_value& out)557 napi_status SetValue(napi_env env, const EventFilterNapi& in, napi_value& out)
558 {
559     LOG_DEBUG("EventFilterNapi -> napi_value ");
560     return napi_ok;
561 }
562 
563 /* napi_value <-> EventType */
GetValue(napi_env env, napi_value in, EventType& out)564 napi_status GetValue(napi_env env, napi_value in, EventType& out)
565 {
566     LOG_DEBUG("napi_value -> EventType ");
567     return napi_ok;
568 }
569 
SetValue(napi_env env, const EventType& in, napi_value& out)570 napi_status SetValue(napi_env env, const EventType& in, napi_value& out)
571 {
572     LOG_DEBUG("EventType -> napi_value ");
573     return napi_ok;
574 }
575 
576 /* napi_value <-> Event */
GetValue(napi_env env, napi_value in, Event& out)577 napi_status GetValue(napi_env env, napi_value in, Event& out)
578 {
579     LOG_DEBUG("napi_value -> Event ");
580     GetNamedPropertyOptional(env, in, "id", out.id);
581     int type = -1;
582     napi_status status = GetNamedProperty(env, in, "type", type);
583     out.type = static_cast<EventType>(type);
584     CHECK_RETURN((status == napi_ok), "invalid entry type", status);
585     GetNamedPropertyOptional(env, in, "title", out.title);
586     GetNamedPropertyOptional(env, in, "location", out.location);
587     status = GetNamedProperty(env, in, "startTime", out.startTime);
588     CHECK_RETURN((status == napi_ok), "invalid entry startTime", status);
589     status = GetNamedProperty(env, in, "endTime", out.endTime);
590     CHECK_RETURN((status == napi_ok), "invalid entry endTime", status);
591     GetNamedPropertyOptional(env, in, "isAllDay", out.isAllDay);
592     GetNamedProperty(env, in, "attendee", out.attendees); // colud be empty not check result
593     GetNamedPropertyOptional(env, in, "timeZone", out.timeZone);
594     GetNamedPropertyOptional(env, in, "reminderTime", out.reminderTime);
595     GetNamedPropertyOptional(env, in, "recurrenceRule", out.recurrenceRule);
596     GetNamedPropertyOptional(env, in, "description", out.description);
597     GetNamedPropertyOptional(env, in, "service", out.service);
598     GetNamedPropertyOptional(env, in, "identifier", out.identifier);
599     GetNamedPropertyOptional(env, in, "isLunar", out.isLunar);
600     return status;
601 }
602 
SetValue(napi_env env, const Event& in, napi_value& out)603 napi_status SetValue(napi_env env, const Event& in, napi_value& out)
604 {
605     LOG_DEBUG("Event -> napi_value");
606     napi_status status = napi_create_object(env, &out);
607     CHECK_RETURN((status == napi_ok), "invalid entry object", status);
608 
609     status = SetNamedProperty(env, "id", in.id.value(), out);
610     CHECK_RETURN((status == napi_ok), "invalid entry id", status);
611 
612     status = SetNamedProperty(env, "type", static_cast<int>(in.type), out);
613     CHECK_RETURN((status == napi_ok), "invalid entry type", status);
614 
615     SetNamedPropertyOptional(env, "location", in.location, out);
616     SetNamedPropertyOptional(env, "title", in.title, out);
617 
618     status = SetNamedProperty(env, "startTime", in.startTime, out);
619     CHECK_RETURN((status == napi_ok), "invalid entry startTime", status);
620 
621     status = SetNamedProperty(env, "endTime", in.endTime, out);
622     CHECK_RETURN((status == napi_ok), "invalid entry endTime", status);
623 
624     SetNamedPropertyOptional(env, "isAllDay", in.isAllDay, out);
625     if (!in.attendees.empty()) {
626         status = SetNamedProperty(env, "attendee", in.attendees, out);
627         CHECK_RETURN((status == napi_ok), "invalid entry attendee", status);
628     }
629     SetNamedPropertyOptional(env, "timeZone", in.timeZone, out);
630     SetNamedPropertyOptional(env, "reminderTime", in.reminderTime, out);
631     SetNamedPropertyOptional(env, "description", in.description, out);
632     SetNamedPropertyOptional(env, "service", in.service, out);
633     SetNamedPropertyOptional(env, "recurrenceRule", in.recurrenceRule, out);
634     SetNamedPropertyOptional(env, "identifier", in.identifier, out);
635     SetNamedPropertyOptional(env, "isLunar", in.isLunar, out);
636     return status;
637 }
638 
639 /* napi_value <-> std::vector<Event> */
GetValue(napi_env env, napi_value in, std::vector<Event>& out)640 napi_status GetValue(napi_env env, napi_value in, std::vector<Event>& out)
641 {
642     LOG_DEBUG("napi_value -> std::vector<Event>");
643     return GetValueArray(env, in, out);
644 }
645 
SetValue(napi_env env, const std::vector<Event>& in, napi_value& out)646 napi_status SetValue(napi_env env, const std::vector<Event>& in, napi_value& out)
647 {
648     LOG_DEBUG("std::vector<Event> -> napi_value");
649     return SetValueArray(env, in, out);
650 }
651 
652 
DefineClass(napi_env env, const std::string& name, const napi_property_descriptor* properties, size_t count, napi_callback newcb)653 napi_value DefineClass(napi_env env, const std::string& name,
654     const napi_property_descriptor* properties, size_t count, napi_callback newcb)
655 {
656     // base64("calendar.calendarmanager") as rootPropName, i.e. global.<root>
657     const std::string rootPropName = "Y2FsZW5kYXIuY2FsZW5kYXJtYW5hZ2Vy";
658     napi_value root = nullptr;
659     bool hasRoot = false;
660     napi_value global = nullptr;
661     napi_get_global(env, &global);
662     napi_has_named_property(env, global, rootPropName.c_str(), &hasRoot);
663     if (hasRoot) {
664         napi_get_named_property(env, global, rootPropName.c_str(), &root);
665     } else {
666         napi_create_object(env, &root);
667         napi_set_named_property(env, global, rootPropName.c_str(), root);
668     }
669 
670     std::string propName = "constructor_of_" + name;
671     napi_value constructor = nullptr;
672     bool hasProp = false;
673     napi_has_named_property(env, root, propName.c_str(), &hasProp);
674     if (hasProp) {
675         napi_get_named_property(env, root, propName.c_str(), &constructor);
676         if (constructor != nullptr) {
677             LOG_DEBUG("got calendar.calendarmanager.%{private}s as constructor", propName.c_str());
678             return constructor;
679         }
680         hasProp = false; // no constructor.
681     }
682 
683     NAPI_CALL(env, napi_define_class(env, name.c_str(), name.size(), newcb, nullptr, count, properties, &constructor));
684     NAPI_ASSERT(env, constructor != nullptr, "napi_define_class failed!");
685 
686     if (!hasProp) {
687         napi_set_named_property(env, root, propName.c_str(), constructor);
688         LOG_DEBUG("save constructor to calendar.calendarmanager.%{private}s", propName.c_str());
689     }
690     return constructor;
691 }
692 
NewWithRef(napi_env env, size_t argc, napi_value* argv, void** out, napi_value constructor)693 napi_ref NewWithRef(napi_env env, size_t argc, napi_value* argv, void** out, napi_value constructor)
694 {
695     napi_value object = nullptr;
696     napi_status status = napi_new_instance(env, constructor, argc, argv, &object);
697     CHECK_RETURN(status == napi_ok, "napi_new_instance failed", nullptr);
698     CHECK_RETURN(object != nullptr, "napi_new_instance failed", nullptr);
699 
700     status = napi_unwrap(env, object, out);
701     CHECK_RETURN(status == napi_ok, "napi_unwrap failed", nullptr);
702     CHECK_RETURN(out != nullptr, "napi_unwrap failed", nullptr);
703 
704     napi_ref ref = nullptr;
705     status = napi_create_reference(env, object, 1, &ref);
706     CHECK_RETURN(status == napi_ok, "napi_create_reference failed!", nullptr);
707     CHECK_RETURN(ref != nullptr, "napi_create_reference failed!", nullptr);
708     return ref;
709 }
710 
Unwrap(napi_env env, napi_value in, void** out, napi_value constructor)711 napi_status Unwrap(napi_env env, napi_value in, void** out, napi_value constructor)
712 {
713     if (constructor != nullptr) {
714         bool isInstance = false;
715         auto status = napi_instanceof(env, in, constructor, &isInstance);
716         if (status != napi_ok) {
717             LOG_ERROR("napi_instanceof failed");
718             return status;
719         }
720         if (!isInstance) {
721             LOG_ERROR("not a instance of *");
722             return napi_invalid_arg;
723         }
724     }
725     return napi_unwrap(env, in, out);
726 }
727 
Equals(napi_env env, napi_value value, napi_ref copy)728 bool Equals(napi_env env, napi_value value, napi_ref copy)
729 {
730     if (copy == nullptr) {
731         return value == nullptr? true : false;
732     }
733 
734     napi_value copyValue = nullptr;
735     napi_get_reference_value(env, copy, &copyValue);
736 
737     bool isEquals = false;
738     napi_strict_equals(env, value, copyValue, &isEquals);
739     return isEquals;
740 }
741 } // namespace OHOS::CalendarApi::NapiUtil
742