aries: Implement DecodeBinaryTagData
Not the prettiest implementation, but it seems to work.
This commit is contained in:
parent
a5bf226d11
commit
8e78492728
|
@ -1,8 +1,9 @@
|
||||||
#include <aries/Tags.hpp>
|
#include <aries/Tags.hpp>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
namespace ls::aries {
|
namespace ls::aries {
|
||||||
|
|
||||||
bool ParseTagFieldsToMap(const std::string_view tagFieldData, TagMap& outMap) {
|
bool ParseTagFieldsToMap(const std::string_view tagFieldData, TagMap& outMap) {
|
||||||
// Nothing to parse,
|
// Nothing to parse,
|
||||||
// which isn't exclusively a failure condition.
|
// which isn't exclusively a failure condition.
|
||||||
if(tagFieldData.empty())
|
if(tagFieldData.empty())
|
||||||
|
@ -83,35 +84,62 @@ namespace ls::aries {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerializeTagFields(const TagMap& map, std::string& outStr) {
|
void SerializeTagFields(const TagMap& map, std::string& outStr) {
|
||||||
std::string tagFieldBuffer{};
|
std::string tagFieldBuffer {};
|
||||||
|
|
||||||
// Reserve a sane amount, to avoid allocations when serializing
|
// Reserve a sane amount, to avoid allocations when serializing
|
||||||
// (in most cases; larger tag count MIGHT still cause some allocation pressure).
|
// (in most cases; larger tag count MIGHT still cause some allocation pressure).
|
||||||
tagFieldBuffer.reserve(512);
|
tagFieldBuffer.reserve(512);
|
||||||
|
|
||||||
// Serialize the tag fields
|
// Serialize the tag fields
|
||||||
for(auto [key, value] : map)
|
for(auto [key, value] : map)
|
||||||
tagFieldBuffer += std::format("{}={}\n", key, value);
|
tagFieldBuffer += std::format("{}={}\n", key, value);
|
||||||
|
|
||||||
// Null terminate it. (TODO: We shouldn't have to do this anymore, std::string does this on its own)
|
|
||||||
//tagFieldBuffer.push_back('\0');
|
|
||||||
|
|
||||||
outStr = std::move(tagFieldBuffer);
|
outStr = std::move(tagFieldBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> DecodeBinaryTagData(std::string_view tagData) {
|
namespace impl {
|
||||||
|
static constexpr std::byte HexCharToByte(char nibble1, char nibble2) {
|
||||||
|
// mmm so sexy
|
||||||
|
constexpr auto convertOneNibble = [](char nibbleChar) -> char {
|
||||||
|
if(nibbleChar >= '0' && nibbleChar <= '9') {
|
||||||
|
return nibbleChar - '0';
|
||||||
|
} else if(nibbleChar >= 'A' && nibbleChar <= 'F') {
|
||||||
|
return nibbleChar - 'A' + 10;
|
||||||
|
} else if(nibbleChar >= 'a' && nibbleChar <= 'f') {
|
||||||
|
return nibbleChar - 'a' + 10;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return static_cast<std::byte>((convertOneNibble(nibble1) << 4) | (convertOneNibble(nibble2)));
|
||||||
|
}
|
||||||
|
} // namespace impl
|
||||||
|
|
||||||
|
std::vector<std::byte> DecodeBinaryTagData(std::string_view tagData) {
|
||||||
// This could be more ergonomic as an optional or something.
|
// This could be more ergonomic as an optional or something.
|
||||||
|
std::vector<std::byte> res;
|
||||||
|
|
||||||
if(tagData.empty())
|
if(tagData.empty())
|
||||||
return {};
|
return res;
|
||||||
|
|
||||||
// Marker for binary data
|
// Aries tagfield's marker for binary data is the $ character.
|
||||||
|
// If this isn't at the start of a binary payload, it's probably invalid.
|
||||||
if(tagData[0] != '$')
|
if(tagData[0] != '$')
|
||||||
return {};
|
return res;
|
||||||
|
|
||||||
// TODO: Implement me fully!
|
// remove the '$' marker from consideration
|
||||||
|
const auto hexPointLength = tagData.length() - 1;
|
||||||
|
const auto byteSize = hexPointLength / 2;
|
||||||
|
|
||||||
return {};
|
res.resize(byteSize);
|
||||||
|
|
||||||
|
const auto dataView = std::string_view(tagData.data() + 1, hexPointLength);
|
||||||
|
for(auto i = 0; i < byteSize; ++i) {
|
||||||
|
res[i] = impl::HexCharToByte(dataView[i * 2], dataView[i * 2 + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ls::aries
|
} // namespace ls::aries
|
|
@ -4,21 +4,21 @@
|
||||||
|
|
||||||
namespace ls::aries {
|
namespace ls::aries {
|
||||||
|
|
||||||
using TagMap = std::unordered_map<std::string, std::string>;
|
/// A map of tag fields and their values.
|
||||||
|
using TagMap = std::unordered_map<std::string, std::string>;
|
||||||
|
|
||||||
/// Parses tag field data to a TagMap.
|
/// Parses tag field data to a TagMap.
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// True on success; false otherwise (TODO: Move to exceptions or error_category)
|
/// True on success; false otherwise (TODO: Move to exceptions or error_category)
|
||||||
bool ParseTagFieldsToMap(const std::string_view tagFieldData, TagMap& outMap);
|
bool ParseTagFieldsToMap(const std::string_view tagFieldData, TagMap& outMap);
|
||||||
|
|
||||||
/// Serializes a TagMap to a string.
|
/// Serializes a TagMap to a string.
|
||||||
void SerializeTagFields(const TagMap& map, std::string& outStr);
|
void SerializeTagFields(const TagMap& map, std::string& outStr);
|
||||||
|
|
||||||
/// Decodes a binary tag to binary data.
|
/// Decodes a binary tag to binary data.
|
||||||
std::vector<u8> DecodeBinaryTagData(std::string_view tagData);
|
std::vector<std::byte> DecodeBinaryTagData(std::string_view tagData);
|
||||||
|
|
||||||
|
// TODO: Maybe also a in-Aries implementation of "CryptoSSC2"/other dirtysock crypto primitives so that we can rehash
|
||||||
|
// passwords to an actually sane password hash (e.g: argon2di).
|
||||||
|
|
||||||
// TODO: Maybe also a in-Aries implementation of "CryptoSSC2"/other dirtysock crypto primitives so that we can rehash
|
} // namespace ls::aries
|
||||||
// passwords to an actually sane password hash (e.g: argon2di).
|
|
||||||
|
|
||||||
}
|
|
|
@ -28,7 +28,13 @@ TEST_CASE("Aries tag field serde functions as expected", "[Aries] [TagFields]")
|
||||||
TEST_CASE("DecodeBinaryTagData() works", "[Aries] [TagFields] [DecodeBinarytagData]") {
|
TEST_CASE("DecodeBinaryTagData() works", "[Aries] [TagFields] [DecodeBinarytagData]") {
|
||||||
// should decode to [ 0x12, 0x34, 0x56, 0x78 ]
|
// should decode to [ 0x12, 0x34, 0x56, 0x78 ]
|
||||||
std::string testCorpus = "$12345678";
|
std::string testCorpus = "$12345678";
|
||||||
const static std::vector<u8> expectedOutput = { 0x12, 0x34, 0x56, 0x78 };
|
const static std::vector<std::byte> expectedOutput = { static_cast<std::byte>(0x12), static_cast<std::byte>(0x34), static_cast<std::byte>(0x56), static_cast<std::byte>(0x78) };
|
||||||
|
|
||||||
REQUIRE(aries::DecodeBinaryTagData(testCorpus) == expectedOutput);
|
std::string testCorpus2 = "$feffffeeffffffff";
|
||||||
|
const static std::vector<std::byte> expectedOutput2 = { static_cast<std::byte>(0xfe), static_cast<std::byte>(0xff), static_cast<std::byte>(0xff), static_cast<std::byte>(0xee), static_cast<std::byte>(0xff), static_cast<std::byte>(0xff), static_cast<std::byte>(0xff), static_cast<std::byte>(0xff) };
|
||||||
|
|
||||||
|
REQUIRE(aries::DecodeBinaryTagData(testCorpus) == expectedOutput);
|
||||||
|
REQUIRE(aries::DecodeBinaryTagData(testCorpus2) == expectedOutput2);
|
||||||
|
|
||||||
|
REQUIRE(aries::DecodeBinaryTagData("invalid").empty());
|
||||||
}
|
}
|
Loading…
Reference in New Issue