// 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