1 /*
2  * Copyright (c) 2024 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 #ifndef OHOS_PREFERENCES_JS_COMMON_JS_SENDABLE_UTILS_H
17 #define OHOS_PREFERENCES_JS_COMMON_JS_SENDABLE_UTILS_H
18 #include <preferences_value.h>
19 
20 #include <iostream>
21 #include <map>
22 #include <string>
23 #include <type_traits>
24 #include <variant>
25 #include <vector>
26 
27 #include "napi/native_api.h"
28 #include "napi/native_common.h"
29 #include "js_native_api_types.h"
30 #include "log_print.h"
31 #include "napi/native_node_api.h"
32 #include "napi_preferences_error.h"
33 #include "preferences_value.h"
34 
35 namespace OHOS::Sendable::JSPreferences {
36 namespace Utils {
37 using Object = NativePreferences::Object;
38 using BigInt = NativePreferences::BigInt;
39 int32_t ConvertFromSendable(napi_env env, napi_value jsValue, bool &output);
40 int32_t ConvertFromSendable(napi_env env, napi_value jsValue, float &output);
41 int32_t ConvertFromSendable(napi_env env, napi_value jsValue, double &output);
42 int32_t ConvertFromSendable(napi_env env, napi_value jsValue, int32_t &output);
43 int32_t ConvertFromSendable(napi_env env, napi_value jsValue, int64_t &output);
44 int32_t ConvertFromSendable(napi_env env, napi_value jsValue, std::vector<uint8_t> &output);
45 int32_t ConvertFromSendable(napi_env env, napi_value jsValue, std::string &output);
46 int32_t ConvertFromSendable(napi_env env, napi_value jsValue, Object &output);
47 int32_t ConvertFromSendable(napi_env env, napi_value jsValue, BigInt &output);
48 int32_t ConvertFromSendable(napi_env env, napi_value jsValue, std::monostate &value);
49 
50 template<typename T>
51 int32_t ConvertFromSendable(napi_env env, napi_value jsValue, std::vector<T> &value);
52 
53 template<typename... Types>
54 int32_t ConvertFromSendable(napi_env env, napi_value jsValue, std::variant<Types...> &value);
55 
56 napi_value ConvertToSendable(napi_env env, int32_t value);
57 napi_value ConvertToSendable(napi_env env, int64_t value);
58 napi_value ConvertToSendable(napi_env env, uint32_t value);
59 napi_value ConvertToSendable(napi_env env, bool value);
60 napi_value ConvertToSendable(napi_env env, float value);
61 napi_value ConvertToSendable(napi_env env, double value);
62 napi_value ConvertToSendable(napi_env env, const std::vector<uint8_t> &value);
63 napi_value ConvertToSendable(napi_env env, const std::string &value);
64 napi_value ConvertToSendable(napi_env env, const OHOS::NativePreferences::Object &value);
65 napi_value ConvertToSendable(napi_env env, const BigInt &value);
66 napi_value ConvertToSendable(napi_env env, const std::monostate &value);
67 template<typename T>
68 std::enable_if_t<std::is_class_v<T>, napi_value> ConvertToSendable(napi_env env, const T &value);
69 template<typename T>
70 std::enable_if_t<!std::is_class_v<T>, napi_value> ConvertToSendable(napi_env env, T value);
71 
72 template<typename T>
73 napi_value ConvertToSendable(napi_env env, const std::vector<T> &value);
74 
75 template<typename... Types>
76 napi_value ConvertToSendable(napi_env env, const std::variant<Types...> &value);
77 
78 template<typename T>
GetCPPValue(napi_env env,napi_value jsValue,T & value)79 int32_t GetCPPValue(napi_env env, napi_value jsValue, T &value)
80 {
81     napi_valuetype type;
82     napi_typeof(env, jsValue, &type);
83     LOG_ERROR("parameter type error, jsValue type is %{public}d", type);
84     return napi_invalid_arg;
85 }
86 
87 template<typename T, typename First, typename... Types>
GetCPPValue(napi_env env,napi_value jsValue,T & value)88 int32_t GetCPPValue(napi_env env, napi_value jsValue, T &value)
89 {
90     First cValue;
91     auto ret = ConvertFromSendable(env, jsValue, cValue);
92     if (ret != PreferencesJsKit::NAPI_TYPE_ERROR) {
93         value = cValue;
94         return ret;
95     }
96     return GetCPPValue<T, Types...>(env, jsValue, value);
97 }
98 
99 template<typename T>
GetSendableValue(napi_env env,const T & value)100 napi_value GetSendableValue(napi_env env, const T &value)
101 {
102     return nullptr;
103 }
104 
105 template<typename T, typename First, typename... Types>
GetSendableValue(napi_env env,const T & value)106 napi_value GetSendableValue(napi_env env, const T &value)
107 {
108     auto *val = std::get_if<First>(&value);
109     if (val != nullptr) {
110         return ConvertToSendable(env, *val);
111     }
112     return GetSendableValue<T, Types...>(env, value);
113 }
114 } // namespace Utils
115 
116 template<typename T>
ConvertFromSendable(napi_env env,napi_value jsValue,std::vector<T> & value)117 int32_t Utils::ConvertFromSendable(napi_env env, napi_value jsValue, std::vector<T> &value)
118 {
119     bool isArray = false;
120     napi_is_array(env, jsValue, &isArray);
121     if (!isArray) {
122         return PreferencesJsKit::NAPI_TYPE_ERROR;
123     }
124 
125     uint32_t arrLen = 0;
126     napi_get_array_length(env, jsValue, &arrLen);
127     if (arrLen == 0) {
128         return napi_ok;
129     }
130 
131     for (size_t i = 0; i < arrLen; ++i) {
132         napi_value element;
133         napi_get_element(env, jsValue, i, &element);
134         T item;
135         auto status = ConvertFromSendable(env, element, item);
136         if (status != napi_ok) {
137             return status;
138         }
139         value.push_back(std::move(item));
140     }
141     return napi_ok;
142 }
143 
144 template<typename... Types>
ConvertFromSendable(napi_env env,napi_value jsValue,std::variant<Types...> & value)145 int32_t Utils::ConvertFromSendable(napi_env env, napi_value jsValue, std::variant<Types...> &value)
146 {
147     return GetCPPValue<decltype(value), Types...>(env, jsValue, value);
148 }
149 
150 template<typename T>
ConvertToSendable(napi_env env,const std::vector<T> & value)151 napi_value Utils::ConvertToSendable(napi_env env, const std::vector<T> &value)
152 {
153     napi_value jsValue;
154     napi_status status = napi_create_sendable_array_with_length(env, value.size(), &jsValue);
155     if (status != napi_ok) {
156         return nullptr;
157     }
158 
159     for (size_t i = 0; i < value.size(); ++i) {
160         napi_set_element(env, jsValue, i, ConvertToSendable(env, static_cast<const T &>(value[i])));
161     }
162     return jsValue;
163 }
164 
165 template<typename... Types>
ConvertToSendable(napi_env env,const std::variant<Types...> & value)166 napi_value Utils::ConvertToSendable(napi_env env, const std::variant<Types...> &value)
167 {
168     return GetSendableValue<decltype(value), Types...>(env, value);
169 }
170 } // namespace OHOS::Sendable::JSPreferences
171 #endif // OHOS_PREFERENCES_JS_COMMON_JS_SENDABLE_UTILS_H
172