Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1dd8a9e authored by Marin Shalamanov's avatar Marin Shalamanov Committed by Android (Google) Code Review
Browse files

Merge "Serialize LightFlattenable trivially copyable objects as LightFlattenable" into sc-dev

parents f51710fe 8c9d2483
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -29,20 +29,29 @@
namespace android {

struct FlattenableHelpers {
    // Helpers for reading and writing POD structures
    template <class T, typename = std::enable_if_t<std::is_trivially_copyable_v<T>>>
    // Helpers for reading and writing POD structures which are not LightFlattenable.
    template <class T,
              typename = std::enable_if_t<
                      std::conjunction_v<std::is_trivially_copyable<T>,
                                         std::negation<std::is_base_of<LightFlattenable<T>, T>>>>>
    static constexpr size_t getFlattenedSize(const T&) {
        return sizeof(T);
    }

    template <class T, typename = std::enable_if_t<std::is_trivially_copyable_v<T>>>
    template <class T,
              typename = std::enable_if_t<
                      std::conjunction_v<std::is_trivially_copyable<T>,
                                         std::negation<std::is_base_of<LightFlattenable<T>, T>>>>>
    static status_t flatten(void** buffer, size_t* size, const T& value) {
        if (*size < sizeof(T)) return NO_MEMORY;
        FlattenableUtils::write(*buffer, *size, value);
        return OK;
    }

    template <class T, typename = std::enable_if_t<std::is_trivially_copyable_v<T>>>
    template <class T,
              typename = std::enable_if_t<
                      std::conjunction_v<std::is_trivially_copyable<T>,
                                         std::negation<std::is_base_of<LightFlattenable<T>, T>>>>>
    static status_t unflatten(const void** buffer, size_t* size, T* value) {
        if (*size < sizeof(T)) return NO_MEMORY;
        FlattenableUtils::read(*buffer, *size, *value);
+62 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ struct TestLightFlattenable : LightFlattenable<TestLightFlattenable> {
    }

    status_t unflatten(void const* buffer, size_t size) {
        int value;
        int32_t value;
        FlattenableUtils::read(buffer, size, value);
        ptr = std::make_unique<int32_t>(value);
        return OK;
@@ -132,5 +132,66 @@ TEST_F(FlattenableHelpersTest, NullOptionalOfLightFlattenable) {
    ASSERT_FALSE(valueRead.has_value());
}

// If a struct is both trivially copyable and light flattenable we should treat it
// as LigthFlattenable.
TEST_F(FlattenableHelpersTest, TriviallyCopyableAndLightFlattenableIsFlattenedAsLightFlattenable) {
    static constexpr int32_t kSizeTag = 1234567;
    static constexpr int32_t kFlattenTag = 987654;
    static constexpr int32_t kUnflattenTag = 5926582;

    struct LightFlattenableAndTriviallyCopyable
          : LightFlattenable<LightFlattenableAndTriviallyCopyable> {
        int32_t value;

        bool isFixedSize() const { return true; }
        size_t getFlattenedSize() const { return kSizeTag; }

        status_t flatten(void* buffer, size_t size) const {
            FlattenableUtils::write(buffer, size, kFlattenTag);
            return OK;
        }

        status_t unflatten(void const*, size_t) {
            value = kUnflattenTag;
            return OK;
        }
    };

    {
        // Verify that getFlattenedSize uses the LightFlattenable overload
        LightFlattenableAndTriviallyCopyable foo;
        EXPECT_EQ(kSizeTag, FlattenableHelpers::getFlattenedSize(foo));
    }

    {
        // Verify that flatten uses the LightFlattenable overload
        std::vector<int8_t> buffer(sizeof(int32_t));
        auto rawBuffer = reinterpret_cast<void*>(buffer.data());
        size_t size = buffer.size();
        LightFlattenableAndTriviallyCopyable foo;
        ASSERT_EQ(OK, FlattenableHelpers::flatten(&rawBuffer, &size, foo));

        auto rawReadBuffer = reinterpret_cast<const void*>(buffer.data());
        int32_t value;
        FlattenableHelpers::unflatten(&rawReadBuffer, &size, &value);
        EXPECT_EQ(kFlattenTag, value);
    }

    {
        // Verify that unflatten uses the LightFlattenable overload
        std::vector<int8_t> buffer(sizeof(int32_t));
        auto rawBuffer = reinterpret_cast<void*>(buffer.data());
        size_t size = buffer.size();
        int32_t value = 4;
        ASSERT_EQ(OK, FlattenableHelpers::flatten(&rawBuffer, &size, value));

        auto rawReadBuffer = reinterpret_cast<const void*>(buffer.data());

        LightFlattenableAndTriviallyCopyable foo;
        FlattenableHelpers::unflatten(&rawReadBuffer, &size, &foo);
        EXPECT_EQ(kUnflattenTag, foo.value);
    }
}

} // namespace
} // namespace android