diff options
Diffstat (limited to 'include/binder/auto_parcelable.h')
-rw-r--r-- | include/binder/auto_parcelable.h | 188 |
1 files changed, 0 insertions, 188 deletions
diff --git a/include/binder/auto_parcelable.h b/include/binder/auto_parcelable.h deleted file mode 100644 index 357615c..0000000 --- a/include/binder/auto_parcelable.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef IORAP_BINDER_AUTO_PARCELABLE_H_ -#define IORAP_BINDER_AUTO_PARCELABLE_H_ - -#include "binder/Parcelable.h" -#include "binder/Parcel.h" -#include "binder/Status.h" - -#include "common/introspection.h" - -namespace iorap { -namespace binder { - -// -// Implements the android::Parcelable interface (readFromParcel, writeToParcel) -// automatically by using compile-time introspection on T. -// -// Requires that 'T' implements introspection by using the IORAP_INTROSPECT_ADAPT_STRUCT macro. -// -template <typename T> -struct AutoParcelable : public ::android::Parcelable { - private: - using Status = android::binder::Status; - using Parcel = android::Parcel; - using Parcelable = android::Parcelable; - using status_t = android::status_t; - - public: - // Write every (introspected) field to the parcel by automatically inferring the correct - // write method to invoke on the parcel from the member type. - status_t writeToParcel(Parcel* parcel) const override { - if (parcel == nullptr) { - return ::android::UNEXPECTED_NULL; - } - - status_t result = android::NO_ERROR; - ::iorap::introspect::for_each_member_field_value(*Self(), [&](auto&& value) { - if (result == android::NO_ERROR) { - result = writeAnyToParcel(/*inout*/parcel, value); - } - }); - - return result; - } - - // Read every (introspected) field to the parcel by automatically inferring the correct - // read method to invoke on the parcel from the member type. - // - // Resilient to partial read failures: A return code other than NO_ERROR means that - // the current value is left unmodified. - status_t readFromParcel(const Parcel* parcel) override { - if (parcel == nullptr) { - return ::android::UNEXPECTED_NULL; - } - - T tmp{*Self()}; - - // Unpack all the parcelable data into a temporary copy. - // Parceling could fail halfway through, in which case - // the original object is unaffected. - - status_t result = android::NO_ERROR; - ::iorap::introspect::for_each_member_field_set_value(tmp, [&](auto field_type) { - // type<?> field_type - - using ValueT = typename decltype(field_type)::type; - - if (result == android::NO_ERROR) { - auto&& [res, read_value] = readAnyFromParcel<ValueT>(/*inout*/parcel); - result = res; - return ::iorap::introspect::aliasing_forward<ValueT>(read_value); - } else { - // TODO: nice-to-have fold over members to early-out on failure. - return ValueT{}; - } - }); - - if (result != android::NO_ERROR) { - return result; - } - - // Success! Now we can copy all the data in a single step. - *Self() = std::move(tmp); - - // TODO: nice-to-have some kind of invariants-checking after reading the parcel data. - - return ::android::NO_ERROR; - } - - private: -#define AUTO_PARCELABLE_BINDER_MAPPING(FN) \ -FN(Byte,int8_t)\ -FN(Int32,int32_t)\ -FN(Uint32,uint32_t)\ -FN(Int64,int64_t)\ -FN(Uint64,uint64_t)\ -FN(Float,float)\ -FN(Double,double)\ -FN(Bool,bool)\ -FN(CString,const char*)\ -FN(String16,const String16&)\ -FN(String16,const std::unique_ptr<String16>&)\ -FN(StrongBinder,const sp<IBinder>&)\ - - template <typename F> - static status_t writeAnyToParcel(Parcel* parcel, const F& value) { - using namespace android; // NOLINT - - // 'F' is the original type of the field here, so it's safe to use it undecayed. - // However, to make matching easier we almost always want to match against the decayed type. - using D = std::decay_t<F>; // [const] [volatile] X[&][&] -> X - - if constexpr (std::is_base_of_v<Parcelable, D>) { - return value.writeToParcel(parcel); - } else if constexpr (std::is_enum_v<D>) { - return writeAnyToParcel(parcel, static_cast<std::underlying_type_t<F>>(value)); -#define AUTO_PARCELABLE_WRITE_TO_PARCEL(fn_name, type_name) \ - } else if constexpr (std::is_same_v<D, std::decay_t<type_name>>) { \ - return parcel->write ## fn_name (value); -AUTO_PARCELABLE_BINDER_MAPPING(AUTO_PARCELABLE_WRITE_TO_PARCEL) - } else if constexpr (std::is_same_v<D, std::string>) { - return parcel->writeUtf8AsUtf16(value); - } else { - STATIC_FAIL(D, "Unsupported type: Add more manual type conversions above^^^"); - } - -#undef AUTO_PARCELABLE_WRITE_TO_PARCEL - } - - template <typename F> - static auto readAnyFromParcel(const Parcel* parcel) { - // returns pair(status_t, ~F~) - using namespace android; - - // Since 'F' is almost always an lvalue reference (due to F=decltype(auto&&), - // we should lose the references, and also any consts. - using D = std::decay_t<F>; - - D value; - status_t result; - - if constexpr (std::is_base_of_v<Parcelable, D>) { - status_t result = value.readFromParcel(/*in*/parcel); - } else if constexpr (std::is_enum_v<D>) { - auto&& [res, val] = readAnyFromParcel<std::underlying_type_t<D>>(parcel); - result = res; - value = static_cast<D>(val); -#define AUTO_PARCELABLE_READ_FROM_PARCEL(fn_name, type_name) \ - } else if constexpr (std::is_same_v<D, std::decay_t<type_name>>) { \ - result = parcel->read ## fn_name (/*out*/&value); -AUTO_PARCELABLE_BINDER_MAPPING(AUTO_PARCELABLE_READ_FROM_PARCEL) - } else if constexpr (std::is_same_v<D, std::string>) { - result = parcel->readUtf8FromUtf16(/*out*/&value); - } else { - STATIC_FAIL(D, "Unsupported type: Add more manual type conversions above^^^"); - } -#undef AUTO_PARCELABLE_READ_FROM_PARCEL - - return std::make_pair(result, std::move(value)); - } - - T* Self() { - return static_cast<T*>(this); - } - const T* Self() const { - return static_cast<const T*>(this); - } -}; - -} // namespace binder -} // namespace iorap - -#endif // IORAP_BINDER_AUTO_PARCELABLE_H_ |