1 /*
2  * Copyright (C) 2021 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 CORE_SERVICE_COMMON_NAPI_NAPI_PARAMETER_UTIL_H
17 #define CORE_SERVICE_COMMON_NAPI_NAPI_PARAMETER_UTIL_H
18 
19 #include <tuple>
20 #include <type_traits>
21 
22 #include "napi/native_api.h"
23 #include "napi/native_node_api.h"
24 
25 namespace OHOS {
26 namespace Telephony {
27 template<typename T, std::enable_if_t<std::is_same_v<T, int32_t>, int32_t> = 0>
GetInputArgvType(T *)28 napi_valuetype GetInputArgvType(T *)
29 {
30     return napi_number;
31 }
32 
33 template<typename T, std::enable_if_t<std::is_same_v<T, napi_ref>, int32_t> = 0>
GetInputArgvType(T *)34 napi_valuetype GetInputArgvType(T *)
35 {
36     return napi_function;
37 }
38 
39 template<typename T, std::enable_if_t<std::is_same_v<T, char>, int32_t> = 0>
GetInputArgvType(T *)40 napi_valuetype GetInputArgvType(T *)
41 {
42     return napi_string;
43 }
44 
45 template<typename T, std::enable_if_t<std::is_same_v<T, std::string>, int32_t> = 0>
GetInputArgvType(T *)46 napi_valuetype GetInputArgvType(T *)
47 {
48     return napi_string;
49 }
50 
51 template<typename T, std::enable_if_t<std::is_same_v<T, napi_value>, int32_t> = 0>
GetInputArgvType(T *)52 napi_valuetype GetInputArgvType(T *)
53 {
54     return napi_object;
55 }
56 
57 template<typename T, std::enable_if_t<std::is_same_v<T, int32_t>, int32_t> = 0>
NapiValueConverted(napi_env env,napi_value arg,T * val)58 napi_status NapiValueConverted(napi_env env, napi_value arg, T *val)
59 {
60     return napi_get_value_int32(env, arg, val);
61 }
62 
63 template<typename T, std::enable_if_t<std::is_same_v<T, napi_ref>, int32_t> = 0>
NapiValueConverted(napi_env env,napi_value arg,T * ref)64 napi_status NapiValueConverted(napi_env env, napi_value arg, T *ref)
65 {
66     return napi_create_reference(env, arg, 1, ref);
67 }
68 
69 template<typename T, std::enable_if_t<std::is_same_v<T, bool>, int32_t> = 0>
NapiValueConverted(napi_env env,napi_value arg,T * res)70 napi_status NapiValueConverted(napi_env env, napi_value arg, T *res)
71 {
72     return napi_get_value_bool(env, arg, res);
73 }
74 
75 template<typename T, std::enable_if_t<std::is_same_v<T, char>, int32_t> = 0>
NapiValueConverted(napi_env env,napi_value arg,T * buf)76 napi_status NapiValueConverted(napi_env env, napi_value arg, T *buf)
77 {
78     size_t result {0};
79     constexpr size_t bufSize { 1024 };
80     return napi_get_value_string_utf8(env, arg, buf, bufSize, &result);
81 }
82 
83 template<typename T, std::enable_if_t<std::is_same_v<T, napi_value>, int32_t> = 0>
NapiValueConverted(napi_env env,napi_value arg,T * npaiValue)84 napi_status NapiValueConverted(napi_env env, napi_value arg, T *npaiValue)
85 {
86     *npaiValue = arg;
87     return napi_ok;
88 }
89 
90 template<typename T, std::enable_if_t<std::is_same_v<T, bool>, int32_t> = 0>
GetNapiValue(napi_env env,T val)91 napi_value GetNapiValue(napi_env env, T val)
92 {
93     napi_value result = nullptr;
94     NAPI_CALL(env, napi_get_boolean(env, val, &result));
95     return result;
96 }
97 
98 template<typename T, std::enable_if_t<std::is_same_v<T, int32_t>, int32_t> = 0>
GetNapiValue(napi_env env,T val)99 napi_value GetNapiValue(napi_env env, T val)
100 {
101     napi_value result = nullptr;
102     NAPI_CALL(env, napi_create_int32(env, val, &result));
103     return result;
104 }
105 
106 template<typename T, std::enable_if_t<std::is_same_v<T, int64_t>, int64_t> = 0>
GetNapiValue(napi_env env,T val)107 napi_value GetNapiValue(napi_env env, T val)
108 {
109     napi_value result = nullptr;
110     NAPI_CALL(env, napi_create_int64(env, val, &result));
111     return result;
112 }
113 
114 template<typename T, std::enable_if_t<std::is_same_v<T, std::string>, int32_t> = 0>
GetNapiValue(napi_env env,const T & val)115 napi_value GetNapiValue(napi_env env, const T &val)
116 {
117     napi_value result = nullptr;
118     NAPI_CALL(env, napi_create_string_utf8(env, val.c_str(), val.length(), &result));
119     return result;
120 }
121 
122 template<typename T, std::enable_if_t<std::is_same_v<T, char>, int32_t> = 0>
GetNapiValue(napi_env env,const T * val)123 napi_value GetNapiValue(napi_env env, const T *val)
124 {
125     napi_value result = nullptr;
126     NAPI_CALL(env, napi_create_string_utf8(env, val, NAPI_AUTO_LENGTH, &result));
127     return result;
128 }
129 
130 template<typename T, std::enable_if_t<std::is_same_v<T, napi_value>, int32_t> = 0>
GetNapiValue(napi_env env,T val)131 napi_value GetNapiValue(napi_env env, T val)
132 {
133     return val;
134 }
135 
136 template<typename T>
SetPropertyToNapiObject(napi_env env,napi_value object,std::string_view name,T value)137 void SetPropertyToNapiObject(napi_env env, napi_value object, std::string_view name, T value)
138 {
139     napi_value propertyValue = GetNapiValue(env, value);
140     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, object, name.data(), propertyValue));
141 }
142 
143 template<typename T>
NapiValueToCppValue(napi_env env,napi_value arg,napi_valuetype argType,T * val)144 napi_status NapiValueToCppValue(napi_env env, napi_value arg, napi_valuetype argType, T *val)
145 {
146     napi_valuetype valueType = napi_undefined;
147     napi_typeof(env, arg, &valueType);
148     if (valueType == argType) {
149         return NapiValueConverted(env, arg, val);
150     }
151     return napi_invalid_arg;
152 }
153 
154 template<typename... Ts, size_t N>
MatchParameters(napi_env env,const napi_value (& argv)[N],size_t argc,std::tuple<Ts...> & theTuple)155 std::optional<NapiError> MatchParameters(
156     napi_env env, const napi_value (&argv)[N], size_t argc, std::tuple<Ts...> &theTuple)
157 {
158     int32_t typeSize = sizeof...(Ts);
159     napi_valuetype valueType = napi_undefined;
160     napi_typeof(env, argv[typeSize - 1], &valueType);
161     if (valueType != napi_function) {
162         typeSize--;
163     }
164     std::vector<napi_valuetype> typeStd(typeSize, napi_undefined);
165 
166     if (argc != typeStd.size()) {
167         return std::optional<NapiError>(ERROR_PARAMETER_COUNTS_INVALID);
168     }
169     bool typeMatched = true;
170     std::apply(
171         [argc, &argv, &typeStd](Ts &... tupleArgs) {
172             size_t index { 0 };
173             ((index < argc ? (typeStd[index++] = GetInputArgvType(tupleArgs)) : true), ...);
174         },
175         theTuple);
176     for (size_t i = 0; i < argc; i++) {
177         napi_valuetype valueType = napi_undefined;
178         napi_typeof(env, argv[i], &valueType);
179         if (valueType != typeStd[i]) {
180             typeMatched = false;
181             break;
182         }
183     }
184     if (typeMatched) {
185         std::apply(
186             [env, argc, &argv](Ts &... tupleArgs) {
187                 size_t index { 0 };
188                 ((index < argc ? NapiValueConverted(env, argv[index++], tupleArgs) : napi_ok), ...);
189             },
190             theTuple);
191         return std::nullopt;
192     }
193     return std::optional<NapiError>(ERROR_PARAMETER_TYPE_INVALID);
194 }
195 } // namespace Telephony
196 } // namespace OHOS
197 #endif
198