// yabridge: a Wine plugin bridge // Copyright (C) 2020-2024 Robbert van der Helm // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #pragma once #include namespace bitsery { namespace ext { /** * A temporary replacement for `bitsery::ext::InPlaceOptional` to avoid * reinitializing the object we're deserializing into if it already holds a * value. This follows the same idea as our `InPLaceVariant`. * * This is copied almost verbatim from `bitsery::ext::InPlaceOptional` (we can't * access the private member, so we couldn't override just the deserialization * method). */ class InPlaceOptional { public: /** * Works with std::optional types * @param alignBeforeData only makes sense when bit-packing enabled, by * default aligns after writing/reading bool state of optional */ explicit InPlaceOptional(bool alignBeforeData = true) : _alignBeforeData{alignBeforeData} {} template void serialize(Ser& ser, const std::optional& obj, Fnc&& fnc) const { ser.boolValue(static_cast(obj)); if (_alignBeforeData) ser.adapter().align(); if (obj) fnc(ser, const_cast(*obj)); } template void deserialize(Des& des, std::optional& obj, Fnc&& fnc) const { bool exists{}; des.boolValue(exists); if (_alignBeforeData) des.adapter().align(); if (exists) { // Reinitializing nontrivial types may be expensive // especially when they reference heap data, so if `obj` // already holds a value then we'll deserialize into the // existing object if constexpr (!std::is_trivial_v) { if (obj) { fnc(des, *obj); return; } } obj = ::bitsery::Access::create(); fnc(des, *obj); } else { obj = std::nullopt; } } private: bool _alignBeforeData; }; } // namespace ext namespace traits { template struct ExtensionTraits> { using TValue = T; static constexpr bool SupportValueOverload = true; static constexpr bool SupportObjectOverload = true; static constexpr bool SupportLambdaOverload = true; }; } // namespace traits } // namespace bitsery