• 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 
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", static_cast<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 = 0;
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         const int appColorLen = 6;
364         const int maxColorLen = 8;
365         while (color.size() < rgbLen) {
366             color = '0' + color;
367         }
368         if (color.size() == rgbLen || color.size() == argbLen) {
369             color = '0' + color;
370         }
371         if (color.size() > maxColorLen) {
372             color = color.substr(color.length() - appColorLen, appColorLen);
373         }
374         color = '#' + color;
375         LOG_DEBUG("config.color: %{public}s", color.c_str());
376         status = SetValue(env, color, colorValue);
377         CHECK_RETURN((status == napi_ok), "invalid entry color", status);
378         napi_set_named_property(env, out, "color", colorValue);
379     }
380     return status;
381 }
382 
GetValue(napi_env env,napi_value in,Location & out)383 napi_status GetValue(napi_env env, napi_value in, Location& out)
384 {
385     LOG_DEBUG("napi_value -> Location ");
386     NapiUtil::GetNamedPropertyOptional(env, in, "location", out.location);
387     NapiUtil::GetNamedPropertyOptional(env, in, "longitude", out.longitude);
388     NapiUtil::GetNamedPropertyOptional(env, in, "latitude", out.latitude);
389     return napi_ok;
390 }
391 
SetValue(napi_env env,const Location & in,napi_value & out)392 napi_status SetValue(napi_env env, const Location& in, napi_value& out)
393 {
394     LOG_DEBUG("Location -> napi_value ");
395     napi_status status = napi_create_object(env, &out);
396     CHECK_RETURN((status == napi_ok), "invalid entry object", status);
397 
398     if (in.location) {
399         napi_value locationValue = nullptr;
400         status = SetValue(env, in.location.value(), locationValue);
401         CHECK_RETURN((status == napi_ok), "invalid location", status);
402         napi_set_named_property(env, out, "location", locationValue);
403     }
404     if (in.longitude) {
405         napi_value value = nullptr;
406         status = SetValue(env, in.longitude.value(), value);
407         CHECK_RETURN((status == napi_ok), "invalid longitude", status);
408         napi_set_named_property(env, out, "longitude", value);
409     }
410     if (in.latitude) {
411         napi_value value = nullptr;
412         status = SetValue(env, in.latitude.value(), value);
413         CHECK_RETURN((status == napi_ok), "invalid latitude", status);
414         napi_set_named_property(env, out, "latitude", value);
415     }
416     return napi_ok;
417 }
418 
419 /* napi_value <-> RecurrenceRule */
GetValue(napi_env env,napi_value in,RecurrenceRule & out)420 napi_status GetValue(napi_env env, napi_value in, RecurrenceRule& out)
421 {
422     LOG_DEBUG("napi_value -> RecurrenceRule ");
423     int recurrence = -1;
424     NapiUtil::GetNamedProperty(env, in, "recurrenceFrequency", recurrence);
425     out.recurrenceFrequency = static_cast<RecurrenceType>(recurrence);
426     NapiUtil::GetNamedPropertyOptional(env, in, "expire", out.expire);
427     NapiUtil::GetNamedPropertyOptional(env, in, "count", out.count);
428     NapiUtil::GetNamedPropertyOptional(env, in, "interval", out.interval);
429     NapiUtil::GetNamedPropertyOptional(env, in, "excludedDates", out.excludedDates);
430     NapiUtil::GetNamedPropertyOptional(env, in, "daysOfWeek", out.daysOfWeek);
431     NapiUtil::GetNamedPropertyOptional(env, in, "daysOfMonth", out.daysOfMonth);
432     NapiUtil::GetNamedPropertyOptional(env, in, "daysOfYear", out.daysOfYear);
433     NapiUtil::GetNamedPropertyOptional(env, in, "weeksOfMonth", out.weeksOfMonth);
434     NapiUtil::GetNamedPropertyOptional(env, in, "weeksOfYear", out.weeksOfYear);
435     NapiUtil::GetNamedPropertyOptional(env, in, "monthsOfYear", out.monthsOfYear);
436     return napi_ok;
437 }
438 
SetValue(napi_env env,const RecurrenceRule & in,napi_value & out)439 napi_status SetValue(napi_env env, const RecurrenceRule& in, napi_value& out)
440 {
441     LOG_DEBUG("RecurrenceRule -> napi_value ");
442     napi_status status = napi_create_object(env, &out);
443     CHECK_RETURN((status == napi_ok), "invalid recurrenceRule", status);
444     status = SetNamedProperty(env, "recurrenceFrequency", in.recurrenceFrequency, out);
445     CHECK_RETURN((status == napi_ok), "invalid recurrenceFrequency", status);
446     SetNamedPropertyOptional(env, "expire", in.expire, out);
447     SetNamedPropertyOptional(env, "count", in.count, out);
448     SetNamedPropertyOptional(env, "interval", in.interval, out);
449     SetNamedPropertyOptional(env, "excludedDates", in.excludedDates, out);
450     SetNamedPropertyOptional(env, "daysOfWeek", in.daysOfWeek, out);
451     SetNamedPropertyOptional(env, "daysOfMonth", in.daysOfMonth, out);
452     SetNamedPropertyOptional(env, "daysOfYear", in.daysOfYear, out);
453     SetNamedPropertyOptional(env, "weeksOfMonth", in.weeksOfMonth, out);
454     SetNamedPropertyOptional(env, "weeksOfYear", in.weeksOfYear, out);
455     SetNamedPropertyOptional(env, "monthsOfYear", in.monthsOfYear, out);
456     return napi_ok;
457 }
458 
459 /* napi_value <-> Attendee */
GetValue(napi_env env,napi_value in,Attendee & out)460 napi_status GetValue(napi_env env, napi_value in, Attendee &out)
461 {
462     LOG_DEBUG("Attendee -> napi_value ");
463     NapiUtil::GetNamedProperty(env, in, "name", out.name);
464     NapiUtil::GetNamedProperty(env, in, "email", out.email);
465     optional<std::string> role = std::nullopt;
466     optional<int> status = std::nullopt;
467     optional<int> type = std::nullopt;
468     NapiUtil::GetNamedPropertyOptional(env, in, "role", role);
469     if (role.has_value()) {
470         if (role == "organizer") {
471             out.role = ORGANIZER;
472         } else {
473             out.role = PARTICIPANT;
474         }
475     }
476     NapiUtil::GetNamedPropertyOptional(env, in, "status", status);
477     if (status.has_value()) {
478         out.status = static_cast<AttendeeStatus>(status.value());
479         LOG_INFO("status.value() %{public}d", status.value());
480     }
481     NapiUtil::GetNamedPropertyOptional(env, in, "type", type);
482     if (type.has_value()) {
483         out.type = static_cast<AttendeeType>(type.value());
484     }
485     return napi_ok;
486 }
487 
SetValue(napi_env env,const Attendee & in,napi_value & out)488 napi_status SetValue(napi_env env, const Attendee& in, napi_value& out)
489 {
490     LOG_DEBUG("napi_value -> Attendee ");
491     napi_status status = napi_create_object(env, &out);
492     CHECK_RETURN((status == napi_ok), "invalid entry object", status);
493 
494     napi_value nameValue = nullptr;
495     status = SetValue(env, in.name, nameValue);
496     CHECK_RETURN((status == napi_ok), "invalid entry name", status);
497     napi_set_named_property(env, out, "name", nameValue);
498     napi_value emailValue = nullptr;
499     status = SetValue(env, in.email, emailValue);
500     CHECK_RETURN((status == napi_ok), "invalid entry type", status);
501     napi_set_named_property(env, out, "email", emailValue);
502     optional<std::string> value = std::nullopt;
503     if (in.role.has_value()) {
504         if (in.role == ORGANIZER) {
505             value = "organizer";
506         } else {
507             value = "participant";
508         }
509     }
510     if (value.has_value()) {
511         SetNamedPropertyOptional(env, "role", value, out);
512     }
513     SetNamedPropertyOptional(env, "status", in.status, out);
514     CHECK_RETURN((status == napi_ok), "invalid status", status);
515     SetNamedPropertyOptional(env, "type", in.type, out);
516     CHECK_RETURN((status == napi_ok), "invalid type", status);
517     return napi_ok;
518 }
519 
520 /* napi_value <-> std::vector<Attendee> */
GetValue(napi_env env,napi_value in,std::vector<Attendee> & out)521 napi_status GetValue(napi_env env, napi_value in, std::vector<Attendee>& out)
522 {
523     LOG_DEBUG("napi_value -> std::vector<Attendee> ");
524     return GetValueArray(env, in, out);
525 }
526 
SetValue(napi_env env,const std::vector<Attendee> & in,napi_value & out)527 napi_status SetValue(napi_env env, const std::vector<Attendee>& in, napi_value& out)
528 {
529     LOG_DEBUG("std::vector<Attendee> -> napi_value ");
530     return SetValueArray(env, in, out);
531 }
532 
GetValue(napi_env env,napi_value in,EventService & out)533 napi_status GetValue(napi_env env, napi_value in, EventService& out)
534 {
535     LOG_DEBUG("napi_value -> EventService");
536     NapiUtil::GetNamedPropertyOptional(env, in, "description", out.description);
537     NapiUtil::GetNamedProperty(env, in, "type", out.type);
538     return NapiUtil::GetNamedProperty(env, in, "uri", out.uri);
539 }
540 
SetValue(napi_env env,const EventService & in,napi_value & out)541 napi_status SetValue(napi_env env, const EventService& in, napi_value& out)
542 {
543     LOG_DEBUG("EventService -> napi_value");
544     napi_status status = napi_create_object(env, &out);
545     CHECK_RETURN((status == napi_ok), "invalid entry object", status);
546 
547     napi_value typeValue = nullptr;
548     status = SetValue(env, in.type, typeValue);
549     CHECK_RETURN((status == napi_ok), "invalid typeValue", status);
550     status = napi_set_named_property(env, out, "type", typeValue);
551     CHECK_RETURN((status == napi_ok), "set type failed", status);
552 
553     napi_value uriValue = nullptr;
554     status = SetValue(env, in.uri, uriValue);
555     CHECK_RETURN((status == napi_ok), "invalid entry type", status);
556     status = napi_set_named_property(env, out, "uri", uriValue);
557     CHECK_RETURN((status == napi_ok), "set uri failed", status);
558 
559     if (in.description) {
560         napi_value descriptionValue = nullptr;
561         status = SetValue(env, in.description.value(), descriptionValue);
562         CHECK_RETURN((status == napi_ok), "invalid description", status);
563         status = napi_set_named_property(env, out, "description", descriptionValue);
564         CHECK_RETURN((status == napi_ok), "set description failed", status);
565     }
566     return status;
567 }
568 
569 /* napi_value <-> EventFilter */
GetValue(napi_env env,napi_value in,EventFilterNapi * & out)570 napi_status GetValue(napi_env env, napi_value in, EventFilterNapi*& out)
571 {
572     LOG_DEBUG("napi_value -> EventFilter ");
573     return EventFilterNapi::ToJson(env, in, out);
574 }
575 
SetValue(napi_env env,const EventFilterNapi & in,napi_value & out)576 napi_status SetValue(napi_env env, const EventFilterNapi& in, napi_value& out)
577 {
578     LOG_DEBUG("EventFilterNapi -> napi_value ");
579     return napi_ok;
580 }
581 
582 /* napi_value <-> EventType */
GetValue(napi_env env,napi_value in,EventType & out)583 napi_status GetValue(napi_env env, napi_value in, EventType& out)
584 {
585     LOG_DEBUG("napi_value -> EventType ");
586     return napi_ok;
587 }
588 
SetValue(napi_env env,const EventType & in,napi_value & out)589 napi_status SetValue(napi_env env, const EventType& in, napi_value& out)
590 {
591     LOG_DEBUG("EventType -> napi_value ");
592     return napi_ok;
593 }
594 
595 /* napi_value <-> Event */
GetValue(napi_env env,napi_value in,Event & out)596 napi_status GetValue(napi_env env, napi_value in, Event& out)
597 {
598     LOG_DEBUG("napi_value -> Event ");
599     GetNamedPropertyOptional(env, in, "id", out.id);
600     int type = -1;
601     napi_status status = GetNamedProperty(env, in, "type", type);
602     out.type = static_cast<EventType>(type);
603     CHECK_RETURN((status == napi_ok), "invalid entry type", status);
604     GetNamedPropertyOptional(env, in, "title", out.title);
605     GetNamedPropertyOptional(env, in, "location", out.location);
606     status = GetNamedProperty(env, in, "startTime", out.startTime);
607     CHECK_RETURN((status == napi_ok), "invalid entry startTime", status);
608     status = GetNamedProperty(env, in, "endTime", out.endTime);
609     CHECK_RETURN((status == napi_ok), "invalid entry endTime", status);
610     GetNamedPropertyOptional(env, in, "isAllDay", out.isAllDay);
611     GetNamedProperty(env, in, "attendee", out.attendees); // colud be empty not check result
612     GetNamedPropertyOptional(env, in, "timeZone", out.timeZone);
613     GetNamedPropertyOptional(env, in, "reminderTime", out.reminderTime);
614     GetNamedPropertyOptional(env, in, "recurrenceRule", out.recurrenceRule);
615     GetNamedPropertyOptional(env, in, "description", out.description);
616     GetNamedPropertyOptional(env, in, "service", out.service);
617     GetNamedPropertyOptional(env, in, "identifier", out.identifier);
618     GetNamedPropertyOptional(env, in, "isLunar", out.isLunar);
619     GetNamedPropertyOptional(env, in, "instanceStartTime", out.instanceStartTime);
620     GetNamedPropertyOptional(env, in, "instanceEndTime", out.instanceEndTime);
621     return status;
622 }
623 
SetValue(napi_env env,const Event & in,napi_value & out)624 napi_status SetValue(napi_env env, const Event& in, napi_value& out)
625 {
626     LOG_DEBUG("Event -> napi_value");
627     napi_status status = napi_create_object(env, &out);
628     CHECK_RETURN((status == napi_ok), "invalid entry object", status);
629 
630     SetNamedPropertyOptional(env, "id", in.id, out);
631 
632     status = SetNamedProperty(env, "type", static_cast<int>(in.type), out);
633     CHECK_RETURN((status == napi_ok), "invalid entry type", status);
634 
635     SetNamedPropertyOptional(env, "location", in.location, out);
636     SetNamedPropertyOptional(env, "title", in.title, out);
637 
638     status = SetNamedProperty(env, "startTime", in.startTime, out);
639     CHECK_RETURN((status == napi_ok), "invalid entry startTime", status);
640 
641     status = SetNamedProperty(env, "endTime", in.endTime, out);
642     CHECK_RETURN((status == napi_ok), "invalid entry endTime", status);
643 
644     SetNamedPropertyOptional(env, "isAllDay", in.isAllDay, out);
645     if (!in.attendees.empty()) {
646         status = SetNamedProperty(env, "attendee", in.attendees, out);
647         CHECK_RETURN((status == napi_ok), "invalid entry attendee", status);
648     }
649     SetNamedPropertyOptional(env, "timeZone", in.timeZone, out);
650     SetNamedPropertyOptional(env, "reminderTime", in.reminderTime, out);
651     SetNamedPropertyOptional(env, "description", in.description, out);
652     SetNamedPropertyOptional(env, "service", in.service, out);
653     SetNamedPropertyOptional(env, "recurrenceRule", in.recurrenceRule, out);
654     SetNamedPropertyOptional(env, "identifier", in.identifier, out);
655     SetNamedPropertyOptional(env, "isLunar", in.isLunar, out);
656     SetNamedPropertyOptional(env, "instanceStartTime", in.instanceStartTime, out);
657     SetNamedPropertyOptional(env, "instanceEndTime", in.instanceEndTime, out);
658     return status;
659 }
660 
661 /* napi_value <-> std::vector<Event> */
GetValue(napi_env env,napi_value in,std::vector<Event> & out)662 napi_status GetValue(napi_env env, napi_value in, std::vector<Event>& out)
663 {
664     LOG_DEBUG("napi_value -> std::vector<Event>");
665     return GetValueArray(env, in, out);
666 }
667 
SetValue(napi_env env,const std::vector<Event> & in,napi_value & out)668 napi_status SetValue(napi_env env, const std::vector<Event>& in, napi_value& out)
669 {
670     LOG_DEBUG("std::vector<Event> -> napi_value");
671     return SetValueArray(env, in, out);
672 }
673 
674 
DefineClass(napi_env env,const std::string & name,const napi_property_descriptor * properties,size_t count,napi_callback newcb)675 napi_value DefineClass(napi_env env, const std::string& name,
676     const napi_property_descriptor* properties, size_t count, napi_callback newcb)
677 {
678     // base64("calendar.calendarmanager") as rootPropName, i.e. global.<root>
679     const std::string rootPropName = "Y2FsZW5kYXIuY2FsZW5kYXJtYW5hZ2Vy";
680     napi_value root = nullptr;
681     bool hasRoot = false;
682     napi_value global = nullptr;
683     napi_get_global(env, &global);
684     napi_has_named_property(env, global, rootPropName.c_str(), &hasRoot);
685     if (hasRoot) {
686         napi_get_named_property(env, global, rootPropName.c_str(), &root);
687     } else {
688         napi_create_object(env, &root);
689         napi_set_named_property(env, global, rootPropName.c_str(), root);
690     }
691 
692     std::string propName = "constructor_of_" + name;
693     napi_value constructor = nullptr;
694     bool hasProp = false;
695     napi_has_named_property(env, root, propName.c_str(), &hasProp);
696     if (hasProp) {
697         napi_get_named_property(env, root, propName.c_str(), &constructor);
698         if (constructor != nullptr) {
699             LOG_DEBUG("got calendar.calendarmanager.%{private}s as constructor", propName.c_str());
700             return constructor;
701         }
702         hasProp = false; // no constructor.
703     }
704 
705     NAPI_CALL(env, napi_define_class(env, name.c_str(), name.size(), newcb, nullptr, count, properties, &constructor));
706     NAPI_ASSERT(env, constructor != nullptr, "napi_define_class failed!");
707 
708     if (!hasProp) {
709         napi_set_named_property(env, root, propName.c_str(), constructor);
710         LOG_DEBUG("save constructor to calendar.calendarmanager.%{private}s", propName.c_str());
711     }
712     return constructor;
713 }
714 
NewWithRef(napi_env env,size_t argc,napi_value * argv,void ** out,napi_value constructor)715 napi_ref NewWithRef(napi_env env, size_t argc, napi_value* argv, void** out, napi_value constructor)
716 {
717     napi_value object = nullptr;
718     napi_status status = napi_new_instance(env, constructor, argc, argv, &object);
719     CHECK_RETURN(status == napi_ok, "napi_new_instance failed", nullptr);
720     CHECK_RETURN(object != nullptr, "napi_new_instance failed", nullptr);
721 
722     status = napi_unwrap(env, object, out);
723     CHECK_RETURN(status == napi_ok, "napi_unwrap failed", nullptr);
724     CHECK_RETURN(out != nullptr, "napi_unwrap failed", nullptr);
725 
726     napi_ref ref = nullptr;
727     status = napi_create_reference(env, object, 1, &ref);
728     CHECK_RETURN(status == napi_ok, "napi_create_reference failed!", nullptr);
729     CHECK_RETURN(ref != nullptr, "napi_create_reference failed!", nullptr);
730     return ref;
731 }
732 
Unwrap(napi_env env,napi_value in,void ** out,napi_value constructor)733 napi_status Unwrap(napi_env env, napi_value in, void** out, napi_value constructor)
734 {
735     if (constructor != nullptr) {
736         bool isInstance = false;
737         auto status = napi_instanceof(env, in, constructor, &isInstance);
738         if (status != napi_ok) {
739             LOG_ERROR("napi_instanceof failed");
740             return status;
741         }
742         if (!isInstance) {
743             LOG_ERROR("not a instance of *");
744             return napi_invalid_arg;
745         }
746     }
747     return napi_unwrap(env, in, out);
748 }
749 
Equals(napi_env env,napi_value value,napi_ref copy)750 bool Equals(napi_env env, napi_value value, napi_ref copy)
751 {
752     if (copy == nullptr) {
753         return value == nullptr? true : false;
754     }
755 
756     napi_value copyValue = nullptr;
757     napi_get_reference_value(env, copy, &copyValue);
758 
759     bool isEquals = false;
760     napi_strict_equals(env, value, copyValue, &isEquals);
761     return isEquals;
762 }
763 } // namespace OHOS::CalendarApi::NapiUtil
764