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 <variant>
20 #include "data_query.h"
21 #include "js_kv_manager.h"
22 #include "change_notification.h"
23 #include "napi/native_api.h"
24 #include "napi/native_common.h"
25 #include "napi/native_node_api.h"
26 #include "datashare_abs_predicates.h"
27 #include "datashare_values_bucket.h"
28 #include "js_error_utils.h"
29 
30 namespace OHOS::DistributedKVStore {
31 class JSUtil final {
32 public:
33     enum {
34         /* Blob's first byte is the blob's data ValueType */
35         STRING = 0,
36         INTEGER = 1,
37         FLOAT = 2,
38         BYTE_ARRAY = 3,
39         BOOLEAN = 4,
40         DOUBLE = 5,
41         INVALID = 255
42     };
43 
44     enum JsApiType {
45         NORMAL = 0,
46         DATASHARE = 1
47     };
48 
49     struct StatusMsg {
50         napi_status status = napi_ok;
51         JsApiType jsApiType = NORMAL;
StatusMsgStatusMsg52         StatusMsg(napi_status status) : status(status) {}
StatusMsgStatusMsg53         StatusMsg(napi_status status, JsApiType jsApiType) : status(status), jsApiType(jsApiType) {}
napi_statusStatusMsg54         operator napi_status()
55         {
56             return status;
57         }
58     };
59 
60     struct JsFeatureSpace {
61         const char* spaceName;
62         const char* nameBase64;
63         bool isComponent;
64     };
65 
66     using JsSchema = class JsSchema;
67     using Blob = OHOS::DistributedKv::Blob;
68     using ChangeNotification = OHOS::DistributedKv::ChangeNotification;
69     using Options = OHOS::DistributedKv::Options;
70     using Entry = OHOS::DistributedKv::Entry;
71     using StoreId = OHOS::DistributedKv::StoreId;
72     using Status = OHOS::DistributedKv::Status;
73     using DataQuery = OHOS::DistributedKv::DataQuery;
74     using ValuesBucket = OHOS::DataShare::DataShareValuesBucket;
75     using ValueObject = OHOS::DataShare::DataShareValueObject;
76     /* for kvStore Put/Get : boolean|string|number|Uint8Array */
77     using KvStoreVariant = std::variant<std::string, int32_t, float, std::vector<uint8_t>, bool, double>;
78     using Descriptor = std::function<std::vector<napi_property_descriptor>()>;
79 
80     static KvStoreVariant Blob2VariantValue(const Blob& blob);
81     static Blob VariantValue2Blob(const KvStoreVariant& value);
82 
83     /* for query value related : number|string|boolean */
84     using QueryVariant = std::variant<std::string, bool, double>;
85 
86     static bool IsSystemApi(JsApiType jsApiType);
87 
88     static StatusMsg GetValue(napi_env env, napi_value in, napi_value& out);
89     static StatusMsg SetValue(napi_env env, napi_value in, napi_value& out);
90     /* napi_value <-> bool */
91     static StatusMsg GetValue(napi_env env, napi_value in, bool& out);
92     static StatusMsg SetValue(napi_env env, const bool& in, napi_value& out);
93 
94     /* napi_value <-> int32_t */
95     static StatusMsg GetValue(napi_env env, napi_value in, int32_t& out);
96     static StatusMsg SetValue(napi_env env, const int32_t& in, napi_value& out);
97 
98     /* napi_value <-> uint32_t */
99     static StatusMsg GetValue(napi_env env, napi_value in, uint32_t& out);
100     static StatusMsg SetValue(napi_env env, const uint32_t& in, napi_value& out);
101 
102     /* napi_value <-> int64_t */
103     static StatusMsg GetValue(napi_env env, napi_value in, int64_t& out);
104     static StatusMsg SetValue(napi_env env, const int64_t& in, napi_value& out);
105 
106     /* napi_value <-> double */
107     static StatusMsg GetValue(napi_env env, napi_value in, double& out);
108     static StatusMsg SetValue(napi_env env, const double& in, napi_value& out);
109 
110     /* napi_value <-> std::string */
111     static StatusMsg GetValue(napi_env env, napi_value in, std::string& out);
112     static StatusMsg SetValue(napi_env env, const std::string& in, napi_value& out);
113 
114     /* napi_value <-> KvStoreVariant */
115     static StatusMsg GetValue(napi_env env, napi_value in, KvStoreVariant& out);
116     static StatusMsg SetValue(napi_env env, const KvStoreVariant& in, napi_value& out);
117 
118     /* napi_value <-> QueryVariant */
119     static StatusMsg GetValue(napi_env env, napi_value in, QueryVariant& out);
120     static StatusMsg SetValue(napi_env env, const QueryVariant& in, napi_value& out);
121 
122     /* napi_value <-> std::vector<std::string> */
123     static StatusMsg GetValue(napi_env env, napi_value in, std::vector<std::string>& out, bool checkLength = true);
124     static StatusMsg SetValue(napi_env env, const std::vector<std::string>& in, napi_value& out);
125 
126     /* napi_value <-> std::vector<uint8_t> */
127     static StatusMsg GetValue(napi_env env, napi_value in, std::vector<uint8_t>& out);
128     static StatusMsg SetValue(napi_env env, const std::vector<uint8_t>& in, napi_value& out);
129 
130     /* napi_value <-> std::vector<int32_t> */
131     static StatusMsg GetValue(napi_env env, napi_value in, std::vector<int32_t>& out);
132     static StatusMsg SetValue(napi_env env, const std::vector<int32_t>& in, napi_value& out);
133 
134     /* napi_value <-> std::vector<uint32_t> */
135     static StatusMsg GetValue(napi_env env, napi_value in, std::vector<uint32_t>& out);
136     static StatusMsg SetValue(napi_env env, const std::vector<uint32_t>& in, napi_value& out);
137 
138     /* napi_value <-> std::vector<int64_t> */
139     static StatusMsg GetValue(napi_env env, napi_value in, std::vector<int64_t>& out);
140     static StatusMsg SetValue(napi_env env, const std::vector<int64_t>& in, napi_value& out);
141 
142     /* napi_value <-> std::vector<double> */
143     static StatusMsg GetValue(napi_env env, napi_value in, std::vector<double>& out);
144     static StatusMsg SetValue(napi_env env, const std::vector<double>& in, napi_value& out);
145 
146     /* napi_value <-> ChangeNotification */
147     static StatusMsg GetValue(napi_env env, napi_value in, ChangeNotification& out, bool hasSchema);
148     static StatusMsg SetValue(napi_env env, const ChangeNotification& in, napi_value& out, bool hasSchema);
149 
150     /* napi_value <-> Options */
151     static StatusMsg GetValue(napi_env env, napi_value in, Options& out);
152     static StatusMsg SetValue(napi_env env, const Options& in, napi_value& out);
153 
154     /* napi_value <-> Entry */
155     static StatusMsg GetValue(napi_env env, napi_value in, Entry& out, bool hasSchema);
156     static StatusMsg SetValue(napi_env env, const Entry& in, napi_value& out, bool hasSchema);
157 
158     /* napi_value <-> Options */
159     static StatusMsg GetValue(napi_env env, napi_value in, std::list<Entry>& out, bool hasSchema);
160     static StatusMsg SetValue(napi_env env, const std::list<Entry>& in, napi_value& out, bool hasSchema);
161 
162     /* napi_value <-> std::vector<Entry> */
163     static StatusMsg GetValue(napi_env env, napi_value in, std::vector<Entry>& out, bool hasSchema);
164     static StatusMsg SetValue(napi_env env, const std::vector<Entry>& in, napi_value& out, bool hasSchema);
165 
166     /* napi_value <-> std::vector<StoreId> */
167     static StatusMsg GetValue(napi_env env, napi_value in, std::vector<StoreId>& out);
168     static StatusMsg SetValue(napi_env env, const std::vector<StoreId>& in, napi_value& out);
169 
170     /* napi_value <-> std::map<std::string, Status> */
171     static StatusMsg GetValue(napi_env env, napi_value in, std::map<std::string, Status>& out);
172     static StatusMsg SetValue(napi_env env, const std::map<std::string, Status>& in, napi_value& out);
173 
174     static StatusMsg GetValue(napi_env env, napi_value in, JsSchema*& out);
175 
176     static StatusMsg GetValue(napi_env env, napi_value in, std::vector<Blob> &out);
177     static StatusMsg GetValue(napi_env env, napi_value in, DataQuery &out);
178 
179     static StatusMsg GetValue(napi_env env, napi_value jsValue, ValueObject::Type &value);
180     static StatusMsg GetValue(napi_env env, napi_value jsValue, ValuesBucket &valuesBucket);
181 
182     static StatusMsg GetValue(napi_env env, napi_value in, ContextParam &param);
183 
184     static StatusMsg GetCurrentAbilityParam(napi_env env, ContextParam &param);
185     /* napi_get_named_property wrapper */
186     template <typename T>
187     static inline napi_status GetNamedProperty(
188         napi_env env, napi_value in, const std::string& prop, T& value, bool optional = false)
189     {
190         auto [status, jsValue] = GetInnerValue(env, in, prop, optional);
191         return (jsValue == nullptr) ? StatusMsg(status) : GetValue(env, jsValue, value);
192     };
193 
IsValid(const std::string & storeId)194     static inline bool IsValid(const std::string& storeId)
195     {
196         if (storeId.empty() || storeId.size() > MAX_STORE_ID_LEN) {
197             return false;
198         }
199         auto iter = std::find_if_not(storeId.begin(), storeId.end(),
200             [](char c) { return (std::isdigit(c) || std::isalpha(c) || c == '_'); });
201         return (iter == storeId.end());
202     }
203 
204     static const std::optional<JsFeatureSpace> GetJsFeatureSpace(const std::string &name);
205     /* napi_define_class  wrapper */
206     static napi_value DefineClass(napi_env env, const std::string &spaceName, const std::string &className,
207         const Descriptor &descriptor, napi_callback ctor);
208     static napi_value GetClass(napi_env env, const std::string &spaceName, const std::string &className);
209     /* napi_new_instance  wrapper */
210     static napi_ref NewWithRef(napi_env env, size_t argc, napi_value* argv, void** out, napi_value constructor);
211 
212     /* napi_unwrap with napi_instanceof */
213     static napi_status Unwrap(napi_env env, napi_value in, void** out, napi_value constructor);
214 
215     static bool Equals(napi_env env, napi_value value, napi_ref copy);
216 
217     static bool IsSystemApp();
218 
219     static bool IsNull(napi_env env, napi_value value);
220 
221 private:
222     enum {
223         /* std::map<key, value> to js::tuple<key, value> */
224         TUPLE_KEY = 0,
225         TUPLE_VALUE,
226         TUPLE_SIZE
227     };
228     static napi_status GetLevel(int32_t level, int32_t &out);
229     static std::pair<napi_status, napi_value> GetInnerValue(
230         napi_env env, napi_value in, const std::string& prop, bool optional);
231     static constexpr int MAX_STORE_ID_LEN = 128;
232 };
233 } // namespace OHOS::DistributedKVStore
234 #endif // OHOS_JS_UTIL_H
235