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_ABILITY_RUNTIME_DATAOBS_UTILS_H
17 #define OHOS_ABILITY_RUNTIME_DATAOBS_UTILS_H
18 #include <climits>
19 #include <list>
20 #include <map>
21 #include <memory>
22 #include <type_traits>
23 #include <variant>
24 #include <vector>
25 
26 #include "iremote_object.h"
27 #include "message_parcel.h"
28 namespace OHOS {
29 template<class T>
30 struct is_container : std::false_type {
31 };
32 template<class T>
33 struct is_container<std::vector<T>> : std::true_type {
34 };
35 template<class T>
36 struct is_container<std::list<T>> : std::true_type {
37 };
38 namespace DataObsUtils {
39 static inline bool Marshal(MessageParcel &data)
40 {
41     return true;
42 }
43 
44 static inline bool Unmarshal(MessageParcel &data)
45 {
46     return true;
47 }
48 
49 static inline bool Marshalling(int64_t input, MessageParcel &data)
50 {
51     return data.WriteInt64(input);
52 }
53 
54 static inline bool Unmarshalling(int64_t &output, MessageParcel &data)
55 {
56     return data.ReadInt64(output);
57 }
58 
59 static inline bool Marshalling(double input, MessageParcel &data)
60 {
61     return data.WriteDouble(input);
62 }
63 
64 static inline bool Unmarshalling(double &output, MessageParcel &data)
65 {
66     return data.ReadDouble(output);
67 }
68 
69 static inline bool Marshalling(bool input, MessageParcel &data)
70 {
71     return data.WriteBool(input);
72 }
73 
74 static inline bool Unmarshalling(bool &output, MessageParcel &data)
75 {
76     return data.ReadBool(output);
77 }
78 
79 static inline bool Marshalling(const std::monostate &input, MessageParcel &data)
80 {
81     return true;
82 }
83 
84 static inline bool Unmarshalling(std::monostate &output, MessageParcel &data)
85 {
86     return true;
87 }
88 
89 static inline bool Marshalling(const std::string &input, MessageParcel &data)
90 {
91     return data.WriteString(input);
92 }
93 
94 static inline bool Unmarshalling(std::string &output, MessageParcel &data)
95 {
96     return data.ReadString(output);
97 }
98 
99 static inline bool Marshalling(const std::vector<uint8_t> &input, MessageParcel &data)
100 {
101     return data.WriteUInt8Vector(input);
102 }
103 
104 static inline bool Unmarshalling(std::vector<uint8_t> &output, MessageParcel &data)
105 {
106     return data.ReadUInt8Vector(&output);
107 }
108 
109 template<typename _OutTp>
110 bool ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data);
111 template<typename _OutTp, typename _First, typename... _Rest>
112 bool ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data);
113 
114 template<typename _InTp>
115 bool WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data);
116 template<typename _InTp, typename _First, typename... _Rest>
117 bool WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data);
118 
119 template<typename... _Types>
120 bool Marshalling(const std::variant<_Types...> &input, MessageParcel &data);
121 template<typename... _Types>
122 bool Unmarshalling(std::variant<_Types...> &output, MessageParcel &data);
123 
124 template<class K, class V>
125 bool Marshalling(const std::map<K, V> &result, MessageParcel &parcel);
126 template<class K, class V>
127 bool Unmarshalling(std::map<K, V> &val, MessageParcel &parcel);
128 
129 template<class T>
130 bool Marshalling(const std::vector<T> &val, MessageParcel &parcel);
131 template<class T>
132 bool Unmarshalling(std::vector<T> &val, MessageParcel &parcel);
133 
134 template<typename T>
135 bool Marshalling(const T &input, MessageParcel &data);
136 template<typename T>
137 bool Unmarshalling(T &output, MessageParcel &data);
138 
139 template<class T, typename std::enable_if<is_container<T>{}, int>::type = 0>
140 bool MarshalToContainer(const T &val, MessageParcel &parcel);
141 template<class T, typename std::enable_if<is_container<T>{}, int>::type = 0>
142 bool UnmarshalFromContainer(T &val, MessageParcel &parcel);
143 
144 template<typename T, typename... Types>
145 bool Marshal(MessageParcel &parcel, const T &first, const Types &...others);
146 
147 template<typename T, typename... Types>
148 bool Unmarshal(MessageParcel &parcel, T &first, Types &...others);
149 } // namespace DataObsUtils
150 
151 template<typename _OutTp>
152 bool DataObsUtils::ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data)
153 {
154     return false;
155 }
156 
157 template<typename _OutTp, typename _First, typename... _Rest>
158 bool DataObsUtils::ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data)
159 {
160     if (step == index) {
161         _First value{};
162         auto success = DataObsUtils::Unmarshalling(value, data);
163         output = value;
164         return success;
165     }
166     return DataObsUtils::ReadVariant<_OutTp, _Rest...>(step + 1, index, output, data);
167 }
168 
169 template<typename _InTp>
170 bool DataObsUtils::WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data)
171 {
172     return false;
173 }
174 
175 template<typename _InTp, typename _First, typename... _Rest>
176 bool DataObsUtils::WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data)
177 {
178     if (step == input.index()) {
179         return DataObsUtils::Marshalling(std::get<_First>(input), data);
180     }
181     return DataObsUtils::WriteVariant<_InTp, _Rest...>(step + 1, input, data);
182 }
183 
184 template<typename... _Types>
185 bool DataObsUtils::Marshalling(const std::variant<_Types...> &input, MessageParcel &data)
186 {
187     uint32_t index = static_cast<uint32_t>(input.index());
188     if (!data.WriteUint32(index)) {
189         return false;
190     }
191 
192     return DataObsUtils::WriteVariant<decltype(input), _Types...>(0, input, data);
193 }
194 
195 template<typename... _Types>
196 bool DataObsUtils::Unmarshalling(std::variant<_Types...> &output, MessageParcel &data)
197 {
198     uint32_t index = data.ReadUint32();
199     if (index >= sizeof...(_Types)) {
200         return false;
201     }
202 
203     return DataObsUtils::ReadVariant<decltype(output), _Types...>(0, index, output, data);
204 }
205 
206 template<class K, class V>
207 bool DataObsUtils::Marshalling(const std::map<K, V> &result, MessageParcel &parcel)
208 {
209     if (!parcel.WriteInt32(static_cast<int32_t>(result.size()))) {
210         return false;
211     }
212     for (const auto &entry : result) {
213         if (!DataObsUtils::Marshalling(entry.first, parcel)) {
214             return false;
215         }
216         if (!DataObsUtils::Marshalling(entry.second, parcel)) {
217             return false;
218         }
219     }
220     return true;
221 }
222 
223 template<class K, class V>
224 bool DataObsUtils::Unmarshalling(std::map<K, V> &val, MessageParcel &parcel)
225 {
226     int32_t size = 0;
227     if (!parcel.ReadInt32(size)) {
228         return false;
229     }
230     if (size < 0) {
231         return false;
232     }
233 
234     size_t readAbleSize = parcel.GetReadableBytes();
235     if ((static_cast<size_t>(size) > readAbleSize) || static_cast<size_t>(size) > val.max_size()) {
236         return false;
237     }
238 
239     for (int32_t i = 0; i < size; i++) {
240         K key;
241         if (!DataObsUtils::Unmarshalling(key, parcel)) {
242             return false;
243         }
244         if (!DataObsUtils::Unmarshalling(val[key], parcel)) {
245             return false;
246         }
247     }
248     return true;
249 }
250 
251 template<class T>
252 bool DataObsUtils::Marshalling(const std::vector<T> &val, MessageParcel &parcel)
253 {
254     return DataObsUtils::MarshalToContainer(val, parcel);
255 }
256 
257 template<class T>
258 bool DataObsUtils::Unmarshalling(std::vector<T> &val, MessageParcel &parcel)
259 {
260     return DataObsUtils::UnmarshalFromContainer(val, parcel);
261 }
262 
263 template<class T, typename std::enable_if<is_container<T>{}, int>::type>
264 bool DataObsUtils::MarshalToContainer(const T &val, MessageParcel &parcel)
265 {
266     if (val.size() > INT_MAX) {
267         return false;
268     }
269 
270     if (!parcel.WriteInt32(static_cast<int32_t>(val.size()))) {
271         return false;
272     }
273 
274     for (auto &v : val) {
275         if (!DataObsUtils::Marshalling(v, parcel)) {
276             return false;
277         }
278     }
279     return true;
280 }
281 
282 template<class T, typename std::enable_if<is_container<T>{}, int>::type>
283 bool DataObsUtils::UnmarshalFromContainer(T &val, MessageParcel &parcel)
284 {
285     int32_t len = parcel.ReadInt32();
286     if (len < 0) {
287         return false;
288     }
289 
290     size_t readAbleSize = parcel.GetReadableBytes();
291     size_t size = static_cast<size_t>(len);
292     if ((size > readAbleSize) || (size > val.max_size())) {
293         return false;
294     }
295 
296     val.clear();
297     for (size_t i = 0; i < size; i++) {
298         typename T::value_type value;
299         if (!DataObsUtils::Unmarshalling(value, parcel)) {
300             return false;
301         }
302         val.emplace_back(std::move(value));
303     }
304     return true;
305 }
306 
307 template<typename T, typename... Types>
308 bool DataObsUtils::Marshal(MessageParcel &parcel, const T &first, const Types &...others)
309 {
310     if (!DataObsUtils::Marshalling(first, parcel)) {
311         return false;
312     }
313     return DataObsUtils::Marshal(parcel, others...);
314 }
315 
316 template<typename T, typename... Types>
317 bool DataObsUtils::Unmarshal(MessageParcel &parcel, T &first, Types &...others)
318 {
319     if (!DataObsUtils::Unmarshalling(first, parcel)) {
320         return false;
321     }
322     return DataObsUtils::Unmarshal(parcel, others...);
323 }
324 } // namespace OHOS
325 #endif //  OHOS_ABILITY_RUNTIME_DATAOBS_UTILS_H