blob: 4c69a689b8699bdee25a83f1a3b943d7d4606ef4 [file] [log] [blame]
// Copyright 2024 Google LLC
//
// 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.
#pragma once
#include "message_intf.hpp"
#include <stdplus/print.hpp>
#include <functional>
#include <optional>
#include <tuple>
#include <type_traits>
#include <utility>
namespace google
{
namespace hoth
{
template <typename Intf, typename... Data>
class MessageReinit : public MessageIntf
{
public:
template <typename... Ts>
explicit MessageReinit(Ts&&... args) : data(std::forward<Ts>(args)...)
{
static_assert(std::is_base_of_v<MessageIntf, Intf>);
try
{
intf.emplace(std::make_from_tuple<Intf>(data));
}
catch (const std::exception& e)
{
stdplus::print(stderr,
"Failed to eager initialize message handler: {}\n",
e.what());
}
}
void send(const uint8_t* buf, size_t size, size_t seek) override
{
return reinitExec(&Intf::send, buf, size, seek);
}
void recv(uint8_t* buf, size_t size, size_t seek) override
{
return reinitExec(&Intf::recv, buf, size, seek);
}
private:
std::tuple<std::remove_cv_t<std::remove_reference_t<Data>>...> data;
std::optional<Intf> intf;
template <typename Func, typename... Args>
auto reinitExec(Func&& func, Args&&... args)
{
if (!intf)
{
intf.emplace(std::make_from_tuple<Intf>(data));
}
try
{
return std::invoke(std::forward<Func>(func), *intf,
std::forward<Args>(args)...);
}
catch (...)
{
intf.reset();
throw;
}
}
};
} // namespace hoth
} // namespace google