95 lines
2.8 KiB
C++
95 lines
2.8 KiB
C++
//-----------------------------------------------------------------------------
|
|
// ___ __ _ _
|
|
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
|
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
|
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
|
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
// Author: Kurt Sassenrath
|
|
// Module: msgpack
|
|
//
|
|
// Default unpacker implementation, utilizing pull-style parsing semantics for
|
|
// deserializing data with an expected structure akin to a schema.
|
|
//
|
|
// The default unpacker maintains some flexibility in how data was originally
|
|
// packed.
|
|
//
|
|
// E.g. If a std::uint8_t is requested, it is perfectly valid to read a uint32
|
|
// format, provided the stored value is less than 255.
|
|
//
|
|
// core/reader (to be renamed verbatim_unpacker) can be utilized in scenarios
|
|
// where code size is critical and exact type matching is not a considerable
|
|
// downside.
|
|
//
|
|
// For schemaless data, the token API can be used instead.
|
|
//
|
|
// Copyright (c) 2023 Kurt Sassenrath.
|
|
//
|
|
// License TBD.
|
|
//-----------------------------------------------------------------------------
|
|
#ifndef msgpack_core_unpacker_910ec357d397ac7e
|
|
#define msgpack_core_unpacker_910ec357d397ac7e
|
|
|
|
#include "parselink/msgpack/core/detail/builtin_unpackable_types.h"
|
|
#include "parselink/msgpack/core/detail/unpackable_concepts.h"
|
|
#include "parselink/msgpack/core/error.h"
|
|
|
|
#include <tl/expected.hpp>
|
|
|
|
#include <cstddef>
|
|
#include <span>
|
|
|
|
namespace msgpack {
|
|
|
|
class unpacker {
|
|
using BufferType = std::span<std::byte const>;
|
|
|
|
public:
|
|
constexpr unpacker(BufferType buff)
|
|
: buff_(buff)
|
|
, curr_(std::begin(buff_))
|
|
, end_(std::end(buff_)) {}
|
|
|
|
// IDK if we need this yet
|
|
struct context {
|
|
decltype(std::begin(BufferType{})) in;
|
|
decltype(std::begin(BufferType{})) end;
|
|
|
|
constexpr auto remaining() noexcept {
|
|
return std::ranges::distance(in, end);
|
|
}
|
|
|
|
template <supports_unpack T>
|
|
constexpr tl::expected<T, error> unpack() noexcept {
|
|
if (remaining() == 0)
|
|
return tl::make_unexpected(error::end_of_message);
|
|
using unpacker_impl = detail::unpacker_impl<T>;
|
|
return unpacker_impl::unpack(*this);
|
|
}
|
|
};
|
|
|
|
template <supports_unpack T>
|
|
constexpr tl::expected<T, error> unpack() noexcept {
|
|
context ctx{curr_, end_};
|
|
auto ret = ctx.unpack<T>();
|
|
if (ret) {
|
|
curr_ = ctx.in;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
constexpr auto remaining() noexcept {
|
|
return std::ranges::distance(curr_, end_);
|
|
}
|
|
|
|
private:
|
|
BufferType buff_;
|
|
decltype(std::begin(buff_)) curr_;
|
|
decltype(std::end(buff_)) end_;
|
|
};
|
|
|
|
} // namespace msgpack
|
|
|
|
#endif // msgpack_core_unpacker_910ec357d397ac7e
|