1 /*
2  * Copyright (c) 2022 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 #ifndef OHOS_JS_UTIL_H
16 #define OHOS_JS_UTIL_H
17 #include <cstdint>
18 #include <map>
19 #include <string>
20 #include <variant>
21 #include <vector>
22 
23 #include "napi/native_api.h"
24 #include "napi/native_node_api.h"
25 #include "object_types.h"
26 
27 namespace OHOS::ObjectStore {
28 class JSUtil final {
29 public:
30     /* napi_value <-> bool */
31     static napi_status GetValue(napi_env env, napi_value in, bool &out);
32     static napi_status SetValue(napi_env env, const bool &in, napi_value &out);
33 
34     /* napi_value <-> double */
35     static napi_status GetValue(napi_env env, napi_value in, double &out);
36     static napi_status SetValue(napi_env env, const double &in, napi_value &out);
37 
38     /* napi_value <-> std::string */
39     static napi_status GetValue(napi_env env, napi_value in, std::string &out);
40     static napi_status SetValue(napi_env env, const std::string &in, napi_value &out);
41 
42     /* napi_value <-> int32_t */
43     static napi_status GetValue(napi_env env, napi_value in, int32_t& out);
44     static napi_status SetValue(napi_env env, const int32_t& in, napi_value& out);
45 
46     static napi_status GetValue(napi_env env, napi_value in, uint32_t& out);
47     static napi_status SetValue(napi_env env, const uint32_t& in, napi_value& out);
48 
49     /* napi_value <-> int64_t */
50     static napi_status GetValue(napi_env env, napi_value in, int64_t& out);
51     static napi_status SetValue(napi_env env, const int64_t& in, napi_value& out);
52 
53     /* napi_value <-> std::vector<std::string> */
54     static napi_status GetValue(napi_env env, napi_value in, std::vector<std::string> &out);
55     static napi_status SetValue(napi_env env, const std::vector<std::string> &in, napi_value &out);
56 
57     /* napi_value <-> std::vector<uint8_t> */
58     static napi_status GetValue(napi_env env, napi_value in, std::vector<uint8_t> &out);
59     static napi_status SetValue(napi_env env, const std::vector<uint8_t> &in, napi_value &out);
60 
61     static napi_status GetValue(napi_env env, napi_value in, Assets &assets);
62 
63     static napi_status GetValue(napi_env env, napi_value in, Asset &asset);
64 
65     static napi_status GetValue(napi_env env, napi_value in, AssetBindInfo &out);
66 
67     static napi_status GetValue(napi_env env, napi_value in, ValuesBucket &out);
68 
69     static napi_status GetValue(napi_env env, napi_value jsValue, std::monostate &out);
70 
71     static void GenerateNapiError(napi_env env, int32_t status, int32_t &errCode, std::string &errMessage);
72 
73     static bool IsNull(napi_env env, napi_value value);
74 
75     template <typename T>
76     static inline napi_status GetNamedProperty(napi_env env, napi_value in, const std::string& prop,
77         T& value, bool optional = false)
78     {
79         bool hasProp = false;
80         napi_status status = napi_has_named_property(env, in, prop.c_str(), &hasProp);
81         if (!hasProp) {
82             status = optional ? napi_ok : napi_generic_failure;
83             return status;
84         }
85 
86         if ((status == napi_ok) && hasProp) {
87             napi_value inner = nullptr;
88             status = napi_get_named_property(env, in, prop.c_str(), &inner);
89             if (!optional && IsNull(env, inner)) {
90                 return napi_generic_failure;
91             }
92             if ((status == napi_ok) && (inner != nullptr)) {
93                 return GetValue(env, inner, value);
94             }
95         }
96         return napi_invalid_arg;
97     };
98 
99     template<typename T>
GetValues(napi_env env,napi_value jsValue,T & value)100     static napi_status GetValues(napi_env env, napi_value jsValue, T &value)
101     {
102         return napi_invalid_arg;
103     }
104 
105     template<typename T, typename First, typename... Types>
GetValues(napi_env env,napi_value jsValue,T & value)106     static napi_status GetValues(napi_env env, napi_value jsValue, T &value)
107     {
108         First cValue;
109         auto ret = GetValue(env, jsValue, cValue);
110         if (ret == napi_ok) {
111             value = cValue;
112             return ret;
113         }
114         return GetValues<T, Types...>(env, jsValue, value);
115     }
116 
117     template<typename... Types>
GetValue(napi_env env,napi_value jsValue,std::variant<Types...> & value)118     static napi_status GetValue(napi_env env, napi_value jsValue, std::variant<Types...> &value)
119     {
120         napi_valuetype type;
121         napi_status status = napi_typeof(env, jsValue, &type);
122         if (status != napi_ok) {
123             return napi_invalid_arg;
124         }
125         if (type == napi_undefined) {
126             return napi_generic_failure;
127         }
128 
129         return GetValues<decltype(value), Types...>(env, jsValue, value);
130     };
131 };
132 
133 #define NAPI_ASSERT_ERRCODE_V9(env, assertion, version, err)                                                       \
134     do {                                                                                                        \
135         if (!(assertion)) {                                                                                     \
136             if ((version) >= 9) {                                                                               \
137                 napi_throw_error((env), std::to_string((err)->GetCode()).c_str(), (err)->GetMessage().c_str()); \
138             }                                                                                                   \
139             return nullptr;                                                                                     \
140         }                                                                                                       \
141     } while (0)
142 
143 #define NAPI_ASSERT_ERRCODE(env, condition, err)                                                           \
144     do {                                                                                                    \
145         if (!(condition)) {                                                                                 \
146             napi_throw_error((env), std::to_string((err)->GetCode()).c_str(), (err)->GetMessage().c_str()); \
147             return nullptr;                                                                                 \
148         }                                                                                                   \
149     } while (0)
150 
151 #define CHECH_STATUS_RETURN_VOID(env, condition, ctxt, info) \
152     do {                                                     \
153         if (!(condition)) {                                  \
154             LOG_ERROR(info);                                 \
155             (ctxt)->status = napi_generic_failure;           \
156             (ctxt)->message = std::string(info);             \
157             return;                                          \
158         }                                                    \
159     } while (0)
160 
161 #define LOG_ERROR_RETURN(condition, message, retVal)             \
162     do {                                                         \
163         if (!(condition)) {                                      \
164             LOG_ERROR("test (" #condition ") failed: " message); \
165             return retVal;                                       \
166         }                                                        \
167     } while (0)
168 
169 #define LOG_ERROR_RETURN_VOID(condition, message)                \
170     do {                                                         \
171         if (!(condition)) {                                      \
172             LOG_ERROR("test (" #condition ") failed: " message); \
173             return;                                              \
174         }                                                        \
175     } while (0)
176 } // namespace OHOS::ObjectStore
177 #endif // OHOS_JS_UTIL_H
178