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