mirror of https://github.com/oxen-io/oxen-mq.git
Fix decoding into a std::byte
Decoding into a std::byte output iterator was not working because the `*out++ = val` assignment doesn't work when the output is std::byte and val is a char/unsigned char/uint8_t. Instead we need to explicitly cast, but figuring out what we have to cast to is a little bit tricky. This PR makes it work (and bumps the version for this and the is_hex fix).
This commit is contained in:
parent
1959f8747d
commit
bd9313bf19
|
@ -9,7 +9,7 @@ include(GNUInstallDirs)
|
|||
|
||||
set(LOKIMQ_VERSION_MAJOR 1)
|
||||
set(LOKIMQ_VERSION_MINOR 2)
|
||||
set(LOKIMQ_VERSION_PATCH 2)
|
||||
set(LOKIMQ_VERSION_PATCH 3)
|
||||
set(LOKIMQ_VERSION "${LOKIMQ_VERSION_MAJOR}.${LOKIMQ_VERSION_MINOR}.${LOKIMQ_VERSION_PATCH}")
|
||||
message(STATUS "lokimq v${LOKIMQ_VERSION}")
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <array>
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
#include "byte_type.h"
|
||||
|
||||
namespace lokimq {
|
||||
|
||||
|
@ -153,7 +154,8 @@ void from_base32z(InputIt begin, InputIt end, OutputIt out) {
|
|||
curr = curr << 5 | detail::b32z_lut.from_b32z(static_cast<unsigned char>(*begin++));
|
||||
if (bits >= 3) {
|
||||
bits -= 3; // Added 5, removing 8
|
||||
*out++ = static_cast<uint8_t>(curr >> bits);
|
||||
*out++ = static_cast<detail::byte_type_t<OutputIt>>(
|
||||
static_cast<uint8_t>(curr >> bits));
|
||||
curr &= (1 << bits) - 1;
|
||||
} else {
|
||||
bits += 5;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <array>
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
#include "byte_type.h"
|
||||
|
||||
namespace lokimq {
|
||||
|
||||
|
@ -190,7 +191,8 @@ void from_base64(InputIt begin, InputIt end, OutputIt out) {
|
|||
bits = 6;
|
||||
else {
|
||||
bits -= 2; // Added 6, removing 8
|
||||
*out++ = static_cast<uint8_t>(curr >> bits);
|
||||
*out++ = static_cast<detail::byte_type_t<OutputIt>>(
|
||||
static_cast<uint8_t>(curr >> bits));
|
||||
curr &= (1 << bits) - 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
// Specializations for assigning from a char into an output iterator, used by hex/base32z/base64
|
||||
// decoding to bytes.
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace lokimq::detail {
|
||||
|
||||
// Fallback - we just try a char
|
||||
template <typename OutputIt, typename = void>
|
||||
struct byte_type { using type = char; };
|
||||
|
||||
// Support for things like std::back_inserter:
|
||||
template <typename OutputIt>
|
||||
struct byte_type<OutputIt, std::void_t<typename OutputIt::container_type>> {
|
||||
using type = typename OutputIt::container_type::value_type; };
|
||||
|
||||
// iterator, raw pointers:
|
||||
template <typename OutputIt>
|
||||
struct byte_type<OutputIt, std::enable_if_t<std::is_reference_v<typename std::iterator_traits<OutputIt>::reference>>> {
|
||||
using type = std::remove_reference_t<typename std::iterator_traits<OutputIt>::reference>; };
|
||||
|
||||
template <typename OutputIt>
|
||||
using byte_type_t = typename byte_type<OutputIt>::type;
|
||||
|
||||
}
|
|
@ -32,6 +32,7 @@
|
|||
#include <array>
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
#include "byte_type.h"
|
||||
|
||||
namespace lokimq {
|
||||
|
||||
|
@ -139,7 +140,8 @@ void from_hex(InputIt begin, InputIt end, OutputIt out) {
|
|||
while (begin != end) {
|
||||
auto a = *begin++;
|
||||
auto b = *begin++;
|
||||
*out++ = from_hex_pair(static_cast<unsigned char>(a), static_cast<unsigned char>(b));
|
||||
*out++ = static_cast<detail::byte_type_t<OutputIt>>(
|
||||
from_hex_pair(static_cast<unsigned char>(a), static_cast<unsigned char>(b)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "lokimq/base32z.h"
|
||||
#include "lokimq/base64.h"
|
||||
#include "common.h"
|
||||
#include <iterator>
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
|
@ -198,3 +199,42 @@ TEST_CASE("base64 encoding/decoding", "[encoding][decoding][base64]") {
|
|||
REQUIRE( lokimq::is_base64(b64_bytes) );
|
||||
REQUIRE( lokimq::from_base64(b64_bytes) == "\xff\x00"sv );
|
||||
}
|
||||
|
||||
TEST_CASE("std::byte decoding", "[decoding][hex][base32z][base64]") {
|
||||
// Decoding to std::byte is a little trickier because you can't assign to a byte without an
|
||||
// explicit cast, which means we have to properly detect that output is going to a std::byte
|
||||
// output.
|
||||
|
||||
// hex
|
||||
auto b_in = "ff42"s;
|
||||
std::vector<std::byte> b_out;
|
||||
lokimq::from_hex(b_in.begin(), b_in.end(), std::back_inserter(b_out));
|
||||
REQUIRE( b_out == std::vector{std::byte{0xff}, std::byte{0x42}} );
|
||||
b_out.emplace_back();
|
||||
lokimq::from_hex(b_in.begin(), b_in.end(), b_out.begin() + 1);
|
||||
REQUIRE( b_out == std::vector{std::byte{0xff}, std::byte{0xff}, std::byte{0x42}} );
|
||||
lokimq::from_hex(b_in.begin(), b_in.end(), b_out.data());
|
||||
REQUIRE( b_out == std::vector{std::byte{0xff}, std::byte{0x42}, std::byte{0x42}} );
|
||||
|
||||
// base32z
|
||||
b_in = "yojky"s;
|
||||
b_out.clear();
|
||||
lokimq::from_base32z(b_in.begin(), b_in.end(), std::back_inserter(b_out));
|
||||
REQUIRE( b_out == std::vector{std::byte{0x04}, std::byte{0x12}, std::byte{0xa0}} );
|
||||
b_out.emplace_back();
|
||||
lokimq::from_base32z(b_in.begin(), b_in.end(), b_out.begin() + 1);
|
||||
REQUIRE( b_out == std::vector{std::byte{0x04}, std::byte{0x04}, std::byte{0x12}, std::byte{0xa0}} );
|
||||
lokimq::from_base32z(b_in.begin(), b_in.end(), b_out.data());
|
||||
REQUIRE( b_out == std::vector{std::byte{0x04}, std::byte{0x12}, std::byte{0xa0}, std::byte{0xa0}} );
|
||||
|
||||
// base64
|
||||
b_in = "yojk"s;
|
||||
b_out.clear();
|
||||
lokimq::from_base64(b_in.begin(), b_in.end(), std::back_inserter(b_out));
|
||||
REQUIRE( b_out == std::vector{std::byte{0xca}, std::byte{0x88}, std::byte{0xe4}} );
|
||||
b_out.emplace_back();
|
||||
lokimq::from_base64(b_in.begin(), b_in.end(), b_out.begin() + 1);
|
||||
REQUIRE( b_out == std::vector{std::byte{0xca}, std::byte{0xca}, std::byte{0x88}, std::byte{0xe4}} );
|
||||
lokimq::from_base64(b_in.begin(), b_in.end(), b_out.data());
|
||||
REQUIRE( b_out == std::vector{std::byte{0xca}, std::byte{0x88}, std::byte{0xe4}, std::byte{0xe4}} );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue