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 OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_SERIALIZABLE_H
17 #define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_SERIALIZABLE_H
18 #include <string>
19 #include <vector>
20 #include "visibility.h"
21 #ifndef JSON_NOEXCEPTION
22 #define JSON_NOEXCEPTION
23 #endif
24 #include <variant>
25 #include <nlohmann/json.hpp>
26 namespace OHOS {
27 namespace DistributedData {
28 #ifndef GET_NAME
29 #define GET_NAME(value) #value
30 #endif
31 struct Serializable {
32 public:
33     using json = nlohmann::json;
34     using size_type = nlohmann::json::size_type;
35     using error_handler_t = nlohmann::detail::error_handler_t;
36 
37     API_EXPORT json Marshall() const;
38     template<typename T>
MarshallSerializable39     static std::string Marshall(T &values)
40     {
41         json root;
42         SetValue(root, values);
43         return root.dump(-1, ' ', false, error_handler_t::replace);
44     }
45 
46     API_EXPORT bool Unmarshall(const std::string &jsonStr);
47     template<typename T>
UnmarshallSerializable48     static bool Unmarshall(const std::string &body, T &values)
49     {
50         return GetValue(ToJson(body), "", values);
51     }
52     API_EXPORT static json ToJson(const std::string &jsonStr);
53     API_EXPORT static bool IsJson(const std::string &jsonStr);
54     virtual bool Marshal(json &node) const = 0;
55     virtual bool Unmarshal(const json &node) = 0;
56     API_EXPORT static bool GetValue(const json &node, const std::string &name, std::string &value);
57     API_EXPORT static bool GetValue(const json &node, const std::string &name, uint32_t &value);
58     API_EXPORT static bool GetValue(const json &node, const std::string &name, int32_t &value);
59     API_EXPORT static bool GetValue(const json &node, const std::string &name, int64_t &value);
60     API_EXPORT static bool GetValue(const json &node, const std::string &name, uint64_t &value);
61     API_EXPORT static bool GetValue(const json &node, const std::string &name, uint16_t &value);
62     API_EXPORT static bool GetValue(const json &node, const std::string &name, bool &value);
63     API_EXPORT static bool GetValue(const json &node, const std::string &name, std::vector<uint8_t> &value);
64     API_EXPORT static bool GetValue(const json &node, const std::string &name, Serializable &value);
65     API_EXPORT static bool SetValue(json &node, const std::string &value);
66     API_EXPORT static bool SetValue(json &node, const uint32_t &value);
67     API_EXPORT static bool SetValue(json &node, const int32_t &value);
68     API_EXPORT static bool SetValue(json &node, const int64_t &value);
69     API_EXPORT static bool SetValue(json &node, const double &value);
70     API_EXPORT static bool SetValue(json &node, const uint64_t &value);
71     API_EXPORT static bool SetValue(json &node, const uint16_t &value);
72     // Use bool & to forbid the const T * auto convert to bool, const bool will convert to const uint32_t &value;
73     template<typename T>
SetValueSerializable74     API_EXPORT static std::enable_if_t<std::is_same_v<T, bool>, bool> SetValue(json &node, const T &value)
75     {
76         node = static_cast<bool>(value);
77         return true;
78     }
79 
80     API_EXPORT static bool SetValue(json &node, const std::vector<uint8_t> &value);
81     API_EXPORT static bool SetValue(json &node, const Serializable &value);
82 
83     template<typename... _Types>
84     API_EXPORT static bool SetValue(json &node, const std::variant<_Types...> &input);
85 
86     template<typename... _Types>
87     API_EXPORT static bool GetValue(const json &node, const std::string &name, std::variant<_Types...> &value);
88 protected:
89     API_EXPORT ~Serializable() = default;
90 
91     template<typename T>
92     static bool GetValue(const json &node, const std::string &name, std::vector<T> &values);
93 
94     template<typename T>
95     static bool SetValue(json &node, const std::vector<T> &values);
96 
97     template<typename T>
98     static bool GetValue(const json &node, const std::string &name, std::map<std::string, T> &values);
99 
100     template<typename T>
101     static bool SetValue(json &node, const std::map<std::string, T> &values);
102 
103     template<typename T>
104     static bool GetValue(const json &node, const std::string &name, T *&value);
105 
106     template<typename T>
107     static bool SetValue(json &node, const T *value);
108 
109     template<typename _OutTp>
110     static bool ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output);
111 
112     template<typename _OutTp, typename _First, typename... _Rest>
113     static bool ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output);
114 
115     template<typename _InTp>
116     static bool WriteVariant(json &node, uint32_t step, const _InTp &input);
117 
118     template<typename _InTp, typename _First, typename... _Rest>
119     static bool WriteVariant(json &node, uint32_t step, const _InTp &input);
120     API_EXPORT static const json &GetSubNode(const json &node, const std::string &name);
121 };
122 
123 template<typename T>
GetValue(const json & node,const std::string & name,std::vector<T> & values)124 bool Serializable::GetValue(const json &node, const std::string &name, std::vector<T> &values)
125 {
126     auto &subNode = GetSubNode(node, name);
127     if (subNode.is_null() || !subNode.is_array()) {
128         return false;
129     }
130     bool result = true;
131     values.resize(subNode.size());
132     for (size_type i = 0; i < subNode.size(); ++i) {
133         result = GetValue(subNode[i], "", values[i]) && result;
134     }
135     return result;
136 }
137 
138 template<typename T>
SetValue(json & node,const std::vector<T> & values)139 bool Serializable::SetValue(json &node, const std::vector<T> &values)
140 {
141     bool result = true;
142     size_type i = 0;
143     node = json::value_t::array;
144     for (const auto &value : values) {
145         result = SetValue(node[i], value) && result;
146         i++;
147     }
148     return result;
149 }
150 
151 template<typename T>
GetValue(const json & node,const std::string & name,std::map<std::string,T> & values)152 bool Serializable::GetValue(const json &node, const std::string &name, std::map<std::string, T> &values)
153 {
154     auto &subNode = GetSubNode(node, name);
155     if (subNode.is_null() || !subNode.is_object()) {
156         return false;
157     }
158     bool result = true;
159     for (auto object = subNode.begin(); object != subNode.end(); ++object) {
160         result = GetValue(object.value(), "", values[object.key()]) && result;
161     }
162     return result;
163 }
164 
165 template<typename T>
SetValue(json & node,const std::map<std::string,T> & values)166 bool Serializable::SetValue(json &node, const std::map<std::string, T> &values)
167 {
168     bool result = true;
169     node = json::value_t::object;
170     for (const auto &[key, value] : values) {
171         result = SetValue(node[key], value) && result;
172     }
173     return result;
174 }
175 
176 template<typename T>
GetValue(const json & node,const std::string & name,T * & value)177 bool Serializable::GetValue(const json &node, const std::string &name, T *&value)
178 {
179     auto &subNode = GetSubNode(node, name);
180     if (subNode.is_null()) {
181         return false;
182     }
183     value = new(std::nothrow) T();
184     if (value == nullptr) {
185         return false;
186     }
187     bool result = GetValue(subNode, "", *value);
188     if (!result) {
189         delete value;
190         value = nullptr;
191     }
192     return result;
193 }
194 
195 template<typename T>
SetValue(json & node,const T * value)196 bool Serializable::SetValue(json &node, const T *value)
197 {
198     if (value == nullptr) {
199         return false;
200     }
201     return SetValue(node, *value);
202 }
203 
204 template<typename... _Types>
SetValue(json & node,const std::variant<_Types...> & input)205 bool Serializable::SetValue(json &node, const std::variant<_Types...> &input)
206 {
207     bool ret = SetValue(node[GET_NAME(type)], input.index());
208     if (!ret) {
209         return ret;
210     }
211     return WriteVariant<decltype(input), _Types...>(node[GET_NAME(value)], 0, input);
212 }
213 
214 template<typename... _Types>
GetValue(const json & node,const std::string & name,std::variant<_Types...> & value)215 bool Serializable::GetValue(const json &node, const std::string &name, std::variant<_Types...> &value)
216 {
217     auto &subNode = GetSubNode(node, name);
218     if (subNode.is_null()) {
219         return false;
220     }
221     uint32_t index;
222     bool ret = GetValue(subNode, GET_NAME(type), index);
223     if (!ret) {
224         return ret;
225     }
226 
227     return Serializable::ReadVariant<decltype(value), _Types...>(subNode, GET_NAME(value), 0, index, value);
228 }
229 
230 template<typename _InTp>
WriteVariant(json & node,uint32_t step,const _InTp & input)231 bool Serializable::WriteVariant(json &node, uint32_t step, const _InTp &input)
232 {
233     return false;
234 }
235 
236 template<typename _OutTp, typename _First, typename... _Rest>
ReadVariant(const json & node,const std::string & name,uint32_t step,uint32_t index,_OutTp & output)237 bool Serializable::ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output)
238 {
239     if (step == index) {
240         _First result;
241         if (!Serializable::GetValue(node, name, result)) {
242             return false;
243         }
244         output = result;
245         return true;
246     }
247     return Serializable::ReadVariant<_OutTp, _Rest...>(node, name, step + 1, index, output);
248 }
249 
250 template<typename _InTp, typename _First, typename... _Rest>
WriteVariant(json & node,uint32_t step,const _InTp & input)251 bool Serializable::WriteVariant(json &node, uint32_t step, const _InTp &input)
252 {
253     if (step == input.index()) {
254         return Serializable::SetValue(node, std::get<_First>(input));
255     }
256     return WriteVariant<_InTp, _Rest...>(node, step + 1, input);
257 }
258 
259 template<typename _OutTp>
ReadVariant(const json & node,const std::string & name,uint32_t step,uint32_t index,_OutTp & output)260 bool Serializable::ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output)
261 {
262     return false;
263 }
264 } // namespace DistributedData
265 } // namespace OHOS
266 #endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_SERIALIZABLE_H
267