WIP Error consolidation, token API

This commit is contained in:
Kurt Sassenrath 2023-09-11 06:54:33 -07:00 committed by Kurt Sassenrath
parent d3c59248a2
commit 89cbbb0f30
12 changed files with 256 additions and 168 deletions

View File

@ -0,0 +1,36 @@
//-----------------------------------------------------------------------------
// ___ __ _ _
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
// / ___/ (_| | | \__ \ __/ /__| | | | | <
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
//
//-----------------------------------------------------------------------------
// Author: Kurt Sassenrath
// Module: msgpack
//
// Error codes for various MessagePack operations.
//
// Copyright (c) 2023 Kurt Sassenrath.
//
// License TBD.
//-----------------------------------------------------------------------------
#ifndef msgpack_error_3fae420b0427164e
#define msgpack_error_3fae420b0427164e
namespace msgpack {
enum class error {
not_implemented, // Feature not implemented.
unsupported, // Feature not supported with current configuration.
end_of_message, // End of the buffer has been reached.
incomplete_message, // Insufficient data in buffer to read a format.
out_of_space, // Insufficient buffer to write a format.
wrong_type, // The format is incompatible with requested type.
bad_value, // Value does not fit within constraints.
will_truncate, // Integer return type is smaller than stored value.
};
} // namespace msgpack
#endif // msgpack_error_3fae420b0427164e

View File

@ -21,6 +21,7 @@
#include <bit>
#include <cstdint>
#include <span>
#include <string>
#include <string_view>
#include <type_traits>

View File

@ -18,6 +18,7 @@
#ifndef msgpack_core_reader_6c2f66f02585565
#define msgpack_core_reader_6c2f66f02585565
#include "error.h"
#include "format.h"
#include "../util/endianness.h"
@ -37,14 +38,6 @@ struct relaxed {}; // Similar formats are acceptable.
struct strict {}; // Formats must exactly match the caller's request.
} // namespace reader_policy
enum class reader_error {
unsupported,
not_implemented,
wrong_type,
end_of_message,
premature_end_of_message,
};
namespace detail {
// Generic mechanism for reading a number of bytes out of an interator.
@ -89,7 +82,7 @@ namespace detail {
};
template <typename T>
using expected = tl::expected<T, reader_error>;
using expected = tl::expected<T, error>;
template <format_type F, typename Iter>
constexpr inline bool accept(Iter& itr) noexcept {
@ -112,7 +105,7 @@ namespace detail {
// Copy off the iterator. Update it at the end _if_ everything goes
// smoothly.
auto cur = itr;
if (!accept<F>(cur)) return tl::make_unexpected(reader_error::wrong_type);
if (!accept<F>(cur)) return tl::make_unexpected(error::wrong_type);
// First thing's first. Read the format's "first_type", which is either
// the payload or the length of the payload. Ensure we have enough data
@ -121,7 +114,7 @@ namespace detail {
using value_type = typename F::value_type;
using diff_type = typename std::iterator_traits<Iter>::difference_type;
if (std::distance(cur, end) < diff_type{sizeof(first_type)}) {
return tl::make_unexpected(reader_error::premature_end_of_message);
return tl::make_unexpected(error::incomplete_message);
}
auto f = read_integral<first_type>(cur);
@ -138,7 +131,7 @@ namespace detail {
// payload. Ensure that the span has enough data and construct the
// value_type accordingly.
if (std::distance(cur, end) < diff_type{f}) {
return tl::make_unexpected(reader_error::premature_end_of_message);
return tl::make_unexpected(error::incomplete_message);
}
itr = cur + f;
@ -258,13 +251,13 @@ namespace detail {
auto v = detail::read<this_format>(itr, end);
if (v.has_value()) {
return v.value();
} else if (v.error() == reader_error::wrong_type) {
} else if (v.error() == error::wrong_type) {
return relaxed_read_impl<fmt, fmtlist, Iter, I + 1>(itr, end);
} else {
return v;
}
} else {
return tl::make_unexpected(reader_error::wrong_type);
return tl::make_unexpected(error::wrong_type);
}
}
@ -289,17 +282,15 @@ template <typename policy = reader_policy::relaxed>
class reader {
public:
using error_code = reader_error;
template <typename T>
using expected = detail::expected<T>;
constexpr reader(std::span<std::byte const> const src) :
constexpr reader(std::span<std::byte const> src) :
data(src), curr(std::begin(data)), end(std::end(data)) {}
template <format_type F>
constexpr expected<typename F::value_type> read() noexcept {
if (curr == end) return tl::make_unexpected(error_code::end_of_message);
if (curr == end) return tl::make_unexpected(error::end_of_message);
return detail::reader_policy_traits<policy>::template read<F>(curr, end);
}

View File

@ -18,6 +18,7 @@
#ifndef msgpack_core_writer_ce48a51aa6ed0858
#define msgpack_core_writer_ce48a51aa6ed0858
#include "error.h"
#include "format.h"
#include "../util/endianness.h"
#include <limits>
@ -39,7 +40,7 @@ enum class writer_error {
//template <typename T>
//struct write_adapter {
//template <typename Itr>
//static constexpr tl::expected<Itr, writer_error> write(T const& t);
//static constexpr tl::expected<Itr, error> write(T const& t);
//};
template <std::size_t N, typename Itr>
@ -126,7 +127,7 @@ struct write_adapter<nil> {
namespace detail {
template <typename T>
using expected = tl::expected<T, writer_error>;
using expected = tl::expected<T, error>;
template <format_type F>
constexpr inline std::size_t calculate_space(typename F::value_type val)
@ -169,7 +170,7 @@ namespace detail {
typename F::value_type&& value, Itr out, Itr const end) {
using diff_type = typename std::iterator_traits<Itr>::difference_type;
if (diff_type(calculate_space<F>(value)) > std::distance(out, end)) {
return tl::make_unexpected(writer_error::out_of_space);
return tl::make_unexpected(error::out_of_space);
}
auto marker = F::marker;
@ -181,7 +182,7 @@ namespace detail {
if constexpr (is_fixtype<F>) {
if (*result > 0xff) {
return tl::make_unexpected(writer_error::bad_value);
return tl::make_unexpected(error::bad_value);
}
if constexpr (F::flags & format::flag::apply_mask) {
marker |= std::byte(*result);
@ -189,7 +190,7 @@ namespace detail {
marker = std::byte(*result);
}
if ((marker & ~F::mask) != F::marker) {
return tl::make_unexpected(writer_error::bad_value);
return tl::make_unexpected(error::bad_value);
}
}
@ -223,8 +224,6 @@ namespace detail {
class writer {
public:
using error_code = writer_error;
template <typename T>
using expected = detail::expected<T>;
@ -235,7 +234,7 @@ public:
constexpr expected<tl::monostate> write(typename F::value_type&& v)
noexcept {
using value_type = typename F::value_type;
if (curr == end) return tl::make_unexpected(error_code::out_of_space);
if (curr == end) return tl::make_unexpected(error::out_of_space);
auto result = detail::write<F>(std::forward<value_type>(v), curr, end);
if (!result) {
return tl::make_unexpected(result.error());

View File

@ -0,0 +1,7 @@
#ifndef msgpack_object_f1f3a9e5c8be6a11
#define msgpack_object_f1f3a9e5c8be6a11
#include "token/type.h"
#include "token/reader.h"
#endif // msgpack_object_f1f3a9e5c8be6a11

View File

@ -0,0 +1,62 @@
//-----------------------------------------------------------------------------
// ___ __ _ _
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
// / ___/ (_| | | \__ \ __/ /__| | | | | <
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
//
//-----------------------------------------------------------------------------
// Author: Kurt Sassenrath
// Module: msgpack
//
// Token-based reader for unpacking MessagePack data. Ensure lifetime of the
// MessagePack buffer exceeds the lifetime of parsed tokens.
//
// TBD: How best to handle arrays and maps.
//
// Copyright (c) 2023 Kurt Sassenrath.
//
// License TBD.
//-----------------------------------------------------------------------------
#ifndef msgpack_token_reader_8daff350a0b1a519
#define msgpack_token_reader_8daff350a0b1a519
#include "type.h"
#include <tl/expected.hpp>
namespace msgpack {
class token_reader {
public:
enum class error {
end_of_message,
incomplete_message
};
constexpr token_reader(std::span<std::byte const> src) noexcept :
data_(src), end_(src.size()) {}
// Read the next token. If the reader currently points to the end of the
// byte buffer, then end_of_message is returned, and if there is still
// some data present in the buffer, then incomplete_message is returned,
// potentially hinting that further buffering is required.
constexpr tl::expected<token, error> read_one() noexcept;
// Read multiple tokens from the byte buffer. The number of tokens parsed
// can be surmised from the returned span of tokens. If the reader
// currently points to the end of the byte buffer, then
// error::end_of_message is returned, and if there is not enough data to
// fully parse a token, then incomplete_message is returned.
constexpr tl::expected<std::span<token>, error> read_some(
std::span<token> token_buffer) noexcept;
private:
std::span<std::byte const> data_;
std::size_t curr_;
std::size_t end_;
};
} // namespace msgpack
#endif // msgpack_token_reader_8daff350a0b1a519

View File

@ -11,10 +11,9 @@
//
// Generic (non-owning) wrapper for MessagePack data.
//
// Emphasis on the "non-owning" aspect of these objects. They're intended for
// use in parsing contexts only where the lifetime of the backing data buffer
// exceeds the lifetime of the object instances themselves, so for strings,
// byte-strings, etc. an explicit copy must be made.
// Emphasis on the "non-owning" aspect of tokens. They're intended for use
// in parsing contexts, where the backing buffer outlives the token instances.
// See token::get for extraction of strings, bytes, etc.
//
// TBD: How best to handle arrays and maps.
//
@ -22,10 +21,11 @@
//
// License TBD.
//-----------------------------------------------------------------------------
#ifndef msgpack_object_f43c22522692063f
#define msgpack_object_f43c22522692063f
#ifndef msgpack_token_type_f43c22522692063f
#define msgpack_token_type_f43c22522692063f
#include "core/format.h"
#include "../core/error.h"
#include "../core/format.h"
#include <string_view>
#include <tl/expected.hpp>
@ -104,7 +104,7 @@ private:
uintptr_t value{};
};
enum class object_type : std::uint8_t {
enum class token_type : std::uint8_t {
invalid,
unsigned_int,
signed_int,
@ -117,80 +117,74 @@ enum class object_type : std::uint8_t {
};
template <size_t WordSize>
class object_base;
// TODO(ksassenrath): Move to own file.
enum class object_error {
wrong_type,
will_truncate
};
class token_base;
// Specialization for 64-bit systems.
template <>
class object_base<8> {
class token_base<8> {
public:
object_base() noexcept = default;
object_base(object_base const& other) noexcept
token_base() noexcept = default;
token_base(token_base const& other) noexcept
: value_(other.value_)
, size_and_type_(other.size_and_type_) {}
template <std::integral T>
explicit object_base(T value) noexcept {
explicit token_base(T value) noexcept {
if constexpr (std::is_same_v<T, bool>) {
size_and_type_.set_enum(object_type::boolean);
size_and_type_.set_enum(token_type::boolean);
value_.b = value;
} else if constexpr (std::is_signed_v<T>) {
size_and_type_.set_enum(object_type::signed_int);
size_and_type_.set_enum(token_type::signed_int);
value_.i = value;
} else {
size_and_type_.set_enum(object_type::unsigned_int);
size_and_type_.set_enum(token_type::unsigned_int);
value_.u = value;
}
}
template <std::convertible_to<std::string_view> T>
explicit object_base(T const& value) noexcept {
explicit token_base(T const& value) noexcept {
std::string_view sv(value);
size_and_type_.set_enum(object_type::string);
size_and_type_.set_enum(token_type::string);
size_and_type_.set_size(sv.size());
value_.str = sv.data();
}
template <std::convertible_to<std::span<std::byte const>> T>
explicit object_base(T const& value) noexcept {
explicit token_base(T const& value) noexcept {
std::span<std::byte const> bv(value);
size_and_type_.set_enum(object_type::bytes);
size_and_type_.set_enum(token_type::bytes);
size_and_type_.set_size(bv.size());
value_.bp = bv.data();
}
constexpr object_type type() const noexcept {
constexpr token_type type() const noexcept {
return size_and_type_.get_enum();
}
template <typename T>
constexpr tl::expected<T, object_error> get() const noexcept;
constexpr tl::expected<T, error> get() const noexcept;
template<std::integral T>
constexpr tl::expected<T, object_error> get() const noexcept {
constexpr tl::expected<T, error> get() const noexcept {
constexpr auto expected_type = std::is_same_v<T, bool> ?
object_type::boolean : std::is_signed_v<T> ?
object_type::signed_int : object_type::unsigned_int;
token_type::boolean : std::is_signed_v<T> ?
token_type::signed_int : token_type::unsigned_int;
if (type() != expected_type) {
return tl::make_unexpected(object_error::wrong_type);
return tl::make_unexpected(error::wrong_type);
}
if constexpr (expected_type == object_type::boolean) {
if constexpr (expected_type == token_type::boolean) {
return T(value_.b);
} else if constexpr (expected_type == object_type::signed_int) {
} else if constexpr (expected_type == token_type::signed_int) {
if (std::numeric_limits<T>::max() < value_.i ||
std::numeric_limits<T>::lowest() > value_.i) {
return tl::make_unexpected(object_error::will_truncate);
return tl::make_unexpected(error::will_truncate);
}
return T(value_.i);
} else {
if (std::numeric_limits<T>::max() < value_.u) {
return tl::make_unexpected(object_error::will_truncate);
return tl::make_unexpected(error::will_truncate);
}
return T(value_.u);
}
@ -203,38 +197,38 @@ private:
char const* str;
std::byte const* bp;
bool b;
object_base* obj;
token_base* obj;
} value_;
size_and_enum<std::uint32_t, object_type> size_and_type_{};
size_and_enum<std::uint32_t, token_type> size_and_type_{};
};
template<>
inline tl::expected<std::string, object_error> object_base<8>::get()
inline tl::expected<std::string, error> token_base<8>::get()
const noexcept
{
if (type() != object_type::string) {
return tl::make_unexpected(object_error::wrong_type);
if (type() != token_type::string) {
return tl::make_unexpected(error::wrong_type);
}
return std::string{value_.str, size_and_type_.get_size()};
}
template<>
constexpr tl::expected<std::string_view, object_error> object_base<8>::get()
constexpr tl::expected<std::string_view, error> token_base<8>::get()
const noexcept
{
if (type() != object_type::string) {
return tl::make_unexpected(object_error::wrong_type);
if (type() != token_type::string) {
return tl::make_unexpected(error::wrong_type);
}
return std::string_view{value_.str, size_and_type_.get_size()};
}
template<>
inline tl::expected<std::vector<std::byte>, object_error> object_base<8>::get()
inline tl::expected<std::vector<std::byte>, error> token_base<8>::get()
const noexcept
{
tl::expected<std::vector<std::byte>, object_error> result;
if (type() != object_type::bytes) {
result = tl::make_unexpected(object_error::wrong_type);
tl::expected<std::vector<std::byte>, error> result;
if (type() != token_type::bytes) {
result = tl::make_unexpected(error::wrong_type);
} else {
result = std::vector<std::byte>(value_.bp,
value_.bp + size_and_type_.get_size());
@ -243,17 +237,18 @@ inline tl::expected<std::vector<std::byte>, object_error> object_base<8>::get()
}
template<>
constexpr tl::expected<std::span<std::byte const>, object_error> object_base<8>::get() const noexcept
constexpr tl::expected<std::span<std::byte const>, error>
token_base<8>::get() const noexcept
{
if (type() != object_type::bytes) {
return tl::make_unexpected(object_error::wrong_type);
if (type() != token_type::bytes) {
return tl::make_unexpected(error::wrong_type);
}
return std::span<std::byte const>(value_.bp, size_and_type_.get_size());
}
using object = object_base<sizeof(void*)>;
using token = token_base<sizeof(void*)>;
} // namespace msgpack
#endif // msgpack_object_f43c22522692063f
#endif // msgpack_token_type_f43c22522692063f

View File

@ -31,9 +31,9 @@ cc_test(
)
cc_test(
name = "object",
name = "token",
srcs = [
"test_object.cpp",
"test_token.cpp",
],
deps = ["test_deps"],
)

View File

@ -67,7 +67,7 @@ using relaxed_reader = msgpack::reader<msgpack::reader_policy::relaxed>;
suite relaxed = [] {
"empty span"_test = [] {
using error = msgpack::reader_error;
using error = msgpack::error;
std::span<std::byte> bytes;
relaxed_reader reader(bytes);
auto v = reader.read<msgpack::format::uint8>();
@ -79,7 +79,7 @@ suite relaxed = [] {
////////////////////////////////////////////////////////////////////////////////
"reader<reader_policy::relaxed>::read<format::uint8>"_test = [] {
using fmt = format::uint8;
using error = msgpack::reader_error;
using error = msgpack::error;
/**
* All bytes 0x00->0x79 are effectively literal uint8s.
*/
@ -102,7 +102,7 @@ suite relaxed = [] {
"reader<reader_policy::relaxed>::read<formats::uint16>"_test = [] {
using fmt = msgpack::format::uint16;
using error = msgpack::reader_error;
using error = msgpack::error;
/**
* All bytes 0x00->0x79 are effectively literal uint8s.
*/

View File

@ -94,7 +94,7 @@ suite reader = [] {
std::span<std::byte> bytes;
msgpack::reader reader(bytes);
auto v = reader.read<msgpack::format::uint8>();
expect(v.error() == msgpack::reader_error::end_of_message);
expect(v.error() == msgpack::error::end_of_message);
};
////////////////////////////////////////////////////////////////////////////////
@ -102,7 +102,7 @@ suite reader = [] {
////////////////////////////////////////////////////////////////////////////////
"reader::read<format::positive_fixint>"_test = [] {
using fmt = format::positive_fixint;
using error = msgpack::reader_error;
using error = msgpack::error;
/**
* All bytes 0x00->0x79 are effectively literal uint8s.
*/
@ -135,7 +135,7 @@ suite reader = [] {
"reader::read<format::uint8>"_test = [] {
using fmt = format::uint8;
using error = msgpack::reader_error;
using error = msgpack::error;
/**
* The uint8 format is 0xcc followed by one byte of data.
*/
@ -154,21 +154,21 @@ suite reader = [] {
expect(result == tl::make_unexpected(error::end_of_message));
}
{
using error = msgpack::reader_error;
using error = msgpack::error;
// Test that partial read fails.
constexpr auto payload = make_bytes(0xcc);
msgpack::reader reader(payload);
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
// Retry, ensure the error remains the same.
result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
};
"reader::read<format::uint16>"_test = [] {
using fmt = format::uint16;
using error = msgpack::reader_error;
using error = msgpack::error;
rng rng;
{
auto samples = rng.get<std::uint16_t, rng_samples_count>();
@ -203,16 +203,16 @@ suite reader = [] {
constexpr auto payload = make_bytes(0xcd);
msgpack::reader reader(payload);
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
constexpr auto payload2 = make_bytes(0xcd, 0x01);
reader = msgpack::reader(payload2);
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
};
"reader::read<format::uint32>"_test = [] {
using fmt = format::uint32;
using error = msgpack::reader_error;
using error = msgpack::error;
rng rng;
auto samples = rng.get<std::uint32_t, rng_samples_count>();
std::vector<std::byte> payload;
@ -236,7 +236,7 @@ suite reader = [] {
for (auto itr = payload.begin() + 1; itr != payload.end(); ++itr) {
msgpack::reader reader({payload.begin(), itr});
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
msgpack::reader reader(payload);
auto result = reader.read<fmt>();
@ -246,7 +246,7 @@ suite reader = [] {
"reader::read<format::uint64>"_test = [] {
using fmt = format::uint64;
using error = msgpack::reader_error;
using error = msgpack::error;
rng rng;
auto samples = rng.get<std::uint64_t, rng_samples_count>();
std::vector<std::byte> payload;
@ -271,7 +271,7 @@ suite reader = [] {
for (auto itr = payload.begin() + 1; itr != payload.end(); ++itr) {
msgpack::reader reader({payload.begin(), itr});
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
msgpack::reader reader(payload);
auto result = reader.read<fmt>();
@ -284,7 +284,7 @@ suite reader = [] {
////////////////////////////////////////////////////////////////////////////////
"reader::read<format::negative_fixint>"_test = [] {
using fmt = format::negative_fixint;
using error = msgpack::reader_error;
using error = msgpack::error;
/**
* All bytes 0x00->0x79 are effectively literal uint8s.
*/
@ -317,7 +317,7 @@ suite reader = [] {
"reader::read<format::int8>"_test = [] {
using fmt = format::int8;
using error = msgpack::reader_error;
using error = msgpack::error;
/**
* The uint8 format is 0xcc followed by one byte of data.
*/
@ -336,21 +336,21 @@ suite reader = [] {
expect(result == tl::make_unexpected(error::end_of_message));
}
{
using error = msgpack::reader_error;
using error = msgpack::error;
// Test that partial read fails.
constexpr auto payload = make_bytes(0xd0);
msgpack::reader reader(payload);
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
// Retry, ensure the error remains the same.
result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
};
"reader::read<format::int16>"_test = [] {
using fmt = format::int16;
using error = msgpack::reader_error;
using error = msgpack::error;
rng rng;
{
auto samples = rng.get<std::int16_t, rng_samples_count>();
@ -385,16 +385,16 @@ suite reader = [] {
constexpr auto payload = make_bytes(0xd1);
msgpack::reader reader(payload);
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
constexpr auto payload2 = make_bytes(0xd1, 0x01);
reader = msgpack::reader(payload2);
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
};
"reader::read<format::int32>"_test = [] {
using fmt = format::int32;
using error = msgpack::reader_error;
using error = msgpack::error;
rng rng;
auto samples = rng.get<std::int32_t, rng_samples_count>();
std::vector<std::byte> payload;
@ -418,7 +418,7 @@ suite reader = [] {
for (auto itr = payload.begin() + 1; itr != payload.end(); ++itr) {
msgpack::reader reader({payload.begin(), itr});
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
msgpack::reader reader(payload);
auto result = reader.read<fmt>();
@ -428,7 +428,7 @@ suite reader = [] {
"reader::read<format::int64>"_test = [] {
using fmt = format::int64;
using error = msgpack::reader_error;
using error = msgpack::error;
rng rng;
auto samples = rng.get<std::int64_t, rng_samples_count>();
std::vector<std::byte> payload;
@ -453,7 +453,7 @@ suite reader = [] {
for (auto itr = payload.begin() + 1; itr != payload.end(); ++itr) {
msgpack::reader reader({payload.begin(), itr});
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
msgpack::reader reader(payload);
auto result = reader.read<fmt>();
@ -467,7 +467,7 @@ suite reader = [] {
"reader::read<fmt::fixstr>"_test = [] {
using fmt = msgpack::format::fixstr;
using error = msgpack::reader_error;
using error = msgpack::error;
constexpr std::string_view sv = "hello";
constexpr auto payload =
cat(make_bytes(0xa0 + sv.size()),
@ -476,7 +476,7 @@ suite reader = [] {
for (auto itr = payload.begin() + 1; itr != payload.end(); ++itr) {
msgpack::reader reader({payload.begin(), itr});
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
msgpack::reader reader(payload);
@ -486,7 +486,7 @@ suite reader = [] {
"reader::read<fmt::str8>"_test = [] {
using fmt = msgpack::format::str8;
using error = msgpack::reader_error;
using error = msgpack::error;
constexpr std::string_view sv = "hello d";
constexpr auto payload =
cat(make_bytes(0xd9, sv.size()),
@ -495,7 +495,7 @@ suite reader = [] {
for (auto itr = payload.begin() + 1; itr != payload.end(); ++itr) {
msgpack::reader reader({payload.begin(), itr});
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
msgpack::reader reader(payload);
@ -505,7 +505,7 @@ suite reader = [] {
"reader::read<fmt::str16>"_test = [] {
using fmt = msgpack::format::str16;
using error = msgpack::reader_error;
using error = msgpack::error;
constexpr std::string_view sv = "hello world";
constexpr auto payload =
cat(make_bytes(0xda, 0x00, sv.size()),
@ -514,7 +514,7 @@ suite reader = [] {
for (auto itr = payload.begin() + 1; itr != payload.end(); ++itr) {
msgpack::reader reader({payload.begin(), itr});
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
msgpack::reader reader(payload);
@ -524,7 +524,7 @@ suite reader = [] {
"reader::read<fmt::str32>"_test = [] {
using fmt = msgpack::format::str32;
using error = msgpack::reader_error;
using error = msgpack::error;
constexpr std::string_view sv = "hello world";
constexpr auto payload =
cat(make_bytes(0xdb, 0x00, 0x00, 0x00, sv.size()),
@ -533,7 +533,7 @@ suite reader = [] {
for (auto itr = payload.begin() + 1; itr != payload.end(); ++itr) {
msgpack::reader reader({payload.begin(), itr});
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
msgpack::reader reader(payload);
@ -547,14 +547,14 @@ suite reader = [] {
"reader::read<fmt::bin8>"_test = [] {
using fmt = msgpack::format::bin8;
using error = msgpack::reader_error;
using error = msgpack::error;
constexpr auto bv = make_bytes(0x0, 0x01, 0x02, 0x04);
constexpr auto payload = cat(make_bytes(0xc4, bv.size()), bv);
for (auto itr = payload.begin() + 1; itr != payload.end(); ++itr) {
msgpack::reader reader({payload.begin(), itr});
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
msgpack::reader reader(payload);
@ -566,7 +566,7 @@ suite reader = [] {
"reader::read<fmt::bin16>"_test = [] {
using fmt = msgpack::format::bin16;
using error = msgpack::reader_error;
using error = msgpack::error;
constexpr auto bv = generate_bytes([] {
auto rg = make_contiguous_range(0, 0xff);
std::vector<std::byte> rg2(rg.size() * 2);
@ -580,7 +580,7 @@ suite reader = [] {
for (auto itr = payload.begin() + 1; itr != payload.end(); ++itr) {
msgpack::reader reader({payload.begin(), itr});
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
msgpack::reader reader(payload);
@ -592,7 +592,7 @@ suite reader = [] {
// TODO: Support this with a proper test payload
"reader::read<fmt::bin32>"_test = [] {
using fmt = msgpack::format::bin32;
using error = msgpack::reader_error;
using error = msgpack::error;
constexpr auto bv = generate_bytes([] {
auto rg = make_contiguous_range(0, 0xff);
std::vector<std::byte> rg2(rg.size() * 2);
@ -608,7 +608,7 @@ suite reader = [] {
for (auto itr = payload.begin() + 1; itr != payload.end(); ++itr) {
msgpack::reader reader({payload.begin(), itr});
auto result = reader.read<fmt>();
expect(result == tl::make_unexpected(error::premature_end_of_message));
expect(result == tl::make_unexpected(error::incomplete_message));
}
msgpack::reader reader(payload);
@ -644,7 +644,7 @@ suite reader = [] {
////////////////////////////////////////////////////////////////////////////////
"reader::read<fmt::fixarray>"_test = [] {
using fmt = msgpack::format::fixarray;
using error = msgpack::reader_error;
using error = msgpack::error;
// A MessagePack array of 5 8-bit unsigned integers.
constexpr auto payload = make_bytes(0x95, 0xcc, 0x85, 0xcc, 0x84, 0xcc,
0x83, 0xcc, 0x82, 0xcc, 0x81);
@ -664,7 +664,7 @@ suite reader = [] {
"reader::read<fmt::array16>"_test = [] {
using fmt = msgpack::format::array16;
using error = msgpack::reader_error;
using error = msgpack::error;
// A MessagePack array of 5 8-bit unsigned integers.
constexpr auto payload =
make_bytes(0xdc, 0x00, 0x05, 0xcc, 0x85, 0xcc, 0x84, 0xcc, 0x83, 0xcc,
@ -685,7 +685,7 @@ suite reader = [] {
"reader::read<fmt::array32>"_test = [] {
using fmt = msgpack::format::array32;
using error = msgpack::reader_error;
using error = msgpack::error;
// A MessagePack array of 5 8-bit unsigned integers.
constexpr auto payload =
make_bytes(0xdd, 0x00, 0x00, 0x00, 0x05, 0xcc, 0x85, 0xcc, 0x84, 0xcc,

View File

@ -1,7 +1,4 @@
#include "source/include/parselink/msgpack/object.h"
#include <string>
#include <tl/expected.hpp>
#include <msgpack/object.h>
#include <msgpack/token/type.h>
#include <boost/ut.hpp>
@ -15,7 +12,7 @@ namespace {
template <typename First, typename... Others>
constexpr bool wrong_types(auto const& obj) {
auto err = tl::make_unexpected(msgpack::object_error::wrong_type);
auto err = tl::make_unexpected(msgpack::error::wrong_type);
if (obj.template get<First>() != err) return false;
if constexpr (sizeof...(Others)) {
return wrong_types<Others...>(obj);
@ -62,39 +59,39 @@ suite size_and_enum = [] {
};
suite assignment_and_access = [] {
"object::object()"_test = [] {
msgpack::object obj;
expect(obj.type() == msgpack::object_type::invalid);
"token::token()"_test = [] {
msgpack::token obj;
expect(obj.type() == msgpack::token_type::invalid);
};
"object::object(bool)"_test = [] {
msgpack::object obj(true);
expect(obj.type() == msgpack::object_type::boolean);
"token::token(bool)"_test = [] {
msgpack::token obj(true);
expect(obj.type() == msgpack::token_type::boolean);
auto retrieved = obj.get<bool>();
expect(retrieved && *retrieved);
expect(wrong_types<int, unsigned, char, std::string_view>(obj));
};
"object::object(std::int8_t)"_test = [] {
"token::token(std::int8_t)"_test = [] {
std::int8_t val = 0x32;
msgpack::object obj(val);
expect(obj.type() == msgpack::object_type::signed_int);
msgpack::token obj(val);
expect(obj.type() == msgpack::token_type::signed_int);
auto retrieved = obj.get<std::int8_t>();
expect(retrieved && *retrieved == val);
expect(wrong_types<bool, unsigned, std::string_view>(obj));
};
"object::object(std::uint8_t)"_test = [] {
"token::token(std::uint8_t)"_test = [] {
std::uint8_t val = 0xaa;
msgpack::object obj(val);
expect(obj.type() == msgpack::object_type::unsigned_int);
msgpack::token obj(val);
expect(obj.type() == msgpack::token_type::unsigned_int);
auto retrieved = obj.get<std::uint8_t>();
expect(retrieved && *retrieved == val);
expect(wrong_types<bool, int, std::string_view>(obj));
};
"object::object(char const*)"_test = [] {
"token::token(char const*)"_test = [] {
std::string extracted_val;
{
char const* val = "hello world";
msgpack::object obj(val);
expect(obj.type() == msgpack::object_type::string);
msgpack::token obj(val);
expect(obj.type() == msgpack::token_type::string);
auto retrieved = obj.get<std::string_view>();
expect(bool(retrieved));
if (*retrieved != std::string_view(val)) {
@ -107,22 +104,22 @@ suite assignment_and_access = [] {
}
expect(extracted_val == "hello world");
};
"object::object(std::string)"_test = [] {
"token::token(std::string)"_test = [] {
std::string val = "std::string";
msgpack::object obj(val);
expect(obj.type() == msgpack::object_type::string);
msgpack::token obj(val);
expect(obj.type() == msgpack::token_type::string);
auto retrieved = obj.get<std::string_view>();
expect(bool(retrieved));
expect(*retrieved == val);
expect(wrong_types<bool, int, unsigned>(obj));
};
"object::object(std::span<byte const>)"_test = [] {
"token::token(std::span<byte const>)"_test = [] {
auto expected_val = make_bytes(0x32, 0xff, 0xaa, 0xce);
std::vector<std::byte> extracted_val;
{
auto val = make_bytes(0x32, 0xff, 0xaa, 0xce);
msgpack::object obj(val);
expect(obj.type() == msgpack::object_type::bytes);
msgpack::token obj(val);
expect(obj.type() == msgpack::token_type::bytes);
auto retrieved = obj.get<std::span<std::byte const>>();
expect(bool(retrieved));
expect(std::equal(retrieved->begin(), retrieved->end(),
@ -139,17 +136,17 @@ suite assignment_and_access = [] {
suite int_truncation = [] {
"unsigned truncation"_test = [] {
msgpack::object obj(0xffffffffu);
expect(obj.type() == msgpack::object_type::unsigned_int);
msgpack::token obj(0xffffffffu);
expect(obj.type() == msgpack::token_type::unsigned_int);
auto retrieved = obj.get<std::uint8_t>();
auto err = tl::make_unexpected(msgpack::object_error::will_truncate);
auto err = tl::make_unexpected(msgpack::error::will_truncate);
expect(retrieved == err);
};
"signed truncation"_test = [] {
msgpack::object obj(-0xffff);
expect(obj.type() == msgpack::object_type::signed_int);
msgpack::token obj(-0xffff);
expect(obj.type() == msgpack::token_type::signed_int);
auto retrieved = obj.get<std::int8_t>();
auto err = tl::make_unexpected(msgpack::object_error::will_truncate);
auto err = tl::make_unexpected(msgpack::error::will_truncate);
expect(retrieved == err);
};
};

View File

@ -98,7 +98,7 @@ suite writer = [] {
"writer::write<format::positive_fixint>"_test = [] {
using fmt = format::positive_fixint;
using error = msgpack::writer_error;
using error = msgpack::error;
std::array<std::byte, 2> payload;
auto constexpr expected = make_bytes(0x32, 0x55);
@ -117,7 +117,7 @@ suite writer = [] {
"writer::write<format::uint8>"_test = [] {
using fmt = format::uint8;
using error = msgpack::writer_error;
using error = msgpack::error;
std::array<std::byte, 4> payload;
auto constexpr expected = make_bytes(0xcc, 0x32, 0xcc, 0x82);
@ -132,7 +132,7 @@ suite writer = [] {
"writer::write<format::uint16>"_test = [] {
using fmt = format::uint16;
using error = msgpack::writer_error;
using error = msgpack::error;
std::array<std::byte, 6> payload;
auto constexpr expected = make_bytes(0xcd, 0x32, 0xcc, 0xcd, 0xaa, 0xff);
@ -147,7 +147,7 @@ suite writer = [] {
"writer::write<format::uint32>"_test = [] {
using fmt = format::uint32;
using error = msgpack::writer_error;
using error = msgpack::error;
std::array<std::byte, 5> payload;
auto constexpr expected = make_bytes(0xce, 0x01, 0x02, 0x03, 0x04);
@ -160,7 +160,7 @@ suite writer = [] {
"writer::write<format::uint64>"_test = [] {
using fmt = format::uint64;
using error = msgpack::writer_error;
using error = msgpack::error;
std::array<std::byte, 9> payload;
auto constexpr expected = make_bytes(
@ -174,7 +174,7 @@ suite writer = [] {
"writer::write<format::negative_fixint>"_test = [] {
using fmt = format::negative_fixint;
using error = msgpack::writer_error;
using error = msgpack::error;
std::array<std::byte, 2> payload;
auto constexpr expected = make_bytes(0xff, 0xe0);
@ -191,7 +191,7 @@ suite writer = [] {
"writer::write<format::int8>"_test = [] {
using fmt = format::int8;
using error = msgpack::writer_error;
using error = msgpack::error;
std::array<std::byte, 4> payload;
auto constexpr expected = make_bytes(0xd0, 0x32, 0xd0, 0xfb);
@ -206,7 +206,7 @@ suite writer = [] {
"writer::write<format::int16>"_test = [] {
using fmt = format::int16;
using error = msgpack::writer_error;
using error = msgpack::error;
std::array<std::byte, 6> payload;
auto constexpr expected = make_bytes(0xd1, 0x32, 0xcc, 0xd1, 0xff, 0xfa);
@ -221,7 +221,7 @@ suite writer = [] {
"writer::write<format::int32>"_test = [] {
using fmt = format::int32;
using error = msgpack::writer_error;
using error = msgpack::error;
std::array<std::byte, 5> payload;
auto constexpr expected = make_bytes(0xd2, 0x01, 0x02, 0x03, 0x04);
@ -234,7 +234,7 @@ suite writer = [] {
"writer::write<format::int64>"_test = [] {
using fmt = format::int64;
using error = msgpack::writer_error;
using error = msgpack::error;
std::array<std::byte, 9> payload;
auto constexpr expected = make_bytes(