Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libcmd/misc-store-flags.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ static void hashFormatCompleter(AddCompletions & completions, size_t index, std:

Args::Flag hashFormatWithDefault(std::string && longName, HashFormat * hf)
{
assert(*hf == nix::HashFormat::SRI);
assert(std::holds_alternative<HashFormatSRI>(hf->raw));
return Args::Flag{
.longName = std::move(longName),
.description = "Hash format (`base16`, `nix32`, `base64`, `sri`). Default: `sri`.",
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/primops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4596,7 +4596,7 @@ static void prim_convertHash(EvalState & state, const PosIdx pos, Value ** args,
HashFormat hf = parseHashFormat(
state.forceStringNoCtx(*iteratorToHashFormat->value, pos, "while evaluating the attribute 'toHashFormat'"));

v.mkString(Hash::parseAny(hash, ha).to_string(hf, hf == HashFormat::SRI), state.mem);
v.mkString(Hash::parseAny(hash, ha).to_string(hf, std::holds_alternative<HashFormatSRI>(hf.raw)), state.mem);
}

static RegisterPrimOp primop_convertHash({
Expand Down
22 changes: 22 additions & 0 deletions src/libutil-tests/base-n.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,26 @@ INSTANTIATE_TEST_SUITE_P(
Base64TrailingParseCase{
"7g91TBvYoYQorRTqo+rYD/i5YnWvUBLnqDhPHxBJDaBW7smuPMeRp6E6JOFuVN9bzN0QnH1ToUU0u9c2CjALEQ== cheesecake"}));

/* ----------------------------------------------------------------------------
* parseBase, parseBaseOpt, printBase
* --------------------------------------------------------------------------*/

TEST(base, testRoundTripPrintParse)
{
for (const Base base : {Base::Base64, Base::Nix32, Base::Base16}) {
ASSERT_EQ(parseBase(printBase(base)), base);
ASSERT_EQ(*parseBaseOpt(printBase(base)), base);
}
}

TEST(base, testParseBaseOptReturnsNullopt)
{
ASSERT_EQ(parseBaseOpt("sha0042"), std::nullopt);
}

TEST(base, testParseBaseThrowsOnInvalid)
{
ASSERT_THROW(parseBase("invalid"), UsageError);
}

} // namespace nix
2 changes: 1 addition & 1 deletion src/libutil-tests/hash.cc
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ TEST(hashParseExplicitFormatUnprefixed, testKnownSHA256Hashes1_wrongBase)

TEST(hashFormat, testRoundTripPrintParse)
{
for (const HashFormat hashFormat : {HashFormat::Base64, HashFormat::Nix32, HashFormat::Base16, HashFormat::SRI}) {
for (const HashFormat hashFormat : {HashFormat{Base::Base64}, {Base::Nix32}, {Base::Base16}, {HashFormat::SRI}}) {
ASSERT_EQ(parseHashFormat(printHashFormat(hashFormat)), hashFormat);
ASSERT_EQ(*parseHashFormatOpt(printHashFormat(hashFormat)), hashFormat);
}
Expand Down
92 changes: 92 additions & 0 deletions src/libutil/base-n.cc
Original file line number Diff line number Diff line change
@@ -1,13 +1,79 @@
#include <string_view>

#include "nix/util/array-from-string-literal.hh"
#include "nix/util/error.hh"
#include "nix/util/logging.hh"
#include "nix/util/util.hh"
#include "nix/util/base-n.hh"
#include "nix/util/base-nix-32.hh"

using namespace std::literals;

namespace nix {

std::optional<Base> parseBaseOpt(std::string_view s)
{
if (s == "base16")
return Base::Base16;
if (s == "nix32")
return Base::Nix32;
if (s == "base32") {
warn(R"("base32" is a deprecated alias for base encoding "nix32".)");
return Base::Nix32;
}
if (s == "base64")
return Base::Base64;
return std::nullopt;
}

Base parseBase(std::string_view s)
{
auto base = parseBaseOpt(s);
if (base)
return *base;
throw UsageError("unknown base encoding '%1%', expected 'base16', 'nix32', or 'base64'", s);
}

std::string_view printBase(Base base)
{
switch (base) {
case Base::Base16:
return "base16";
case Base::Nix32:
return "nix32";
case Base::Base64:
return "base64";
}
unreachable();
}

std::string_view printBaseDisplay(Base base)
{
switch (base) {
case Base::Base16:
return "base-16";
case Base::Nix32:
return "Nix base-32";
case Base::Base64:
return "base-64";
}
unreachable();
}

std::optional<Base> baseFromEncodedSize(size_t encodedSize, size_t decodedSize)
{
if (encodedSize == base16::encodedLength(decodedSize))
return Base::Base16;

if (encodedSize == BaseNix32::encodedLength(decodedSize))
return Base::Nix32;

if (encodedSize == base64::encodedLength(decodedSize))
return Base::Base64;

return std::nullopt;
}

constexpr static const std::array<char, 16> base16Chars = "0123456789abcdef"_arrayNoNull;

std::string base16::encode(std::span<const std::byte> b)
Expand Down Expand Up @@ -111,4 +177,30 @@ std::string base64::decode(std::string_view s)
return res;
}

decltype(base16::encode) * encodeForBase(Base base)
{
switch (base) {
case Base::Base16:
return base16::encode;
case Base::Nix32:
return BaseNix32::encode;
case Base::Base64:
return base64::encode;
}
unreachable();
}

decltype(base16::decode) * decodeForBase(Base base)
{
switch (base) {
case Base::Base16:
return base16::decode;
case Base::Nix32:
return BaseNix32::decode;
case Base::Base64:
return base64::decode;
}
unreachable();
}

} // namespace nix
Loading
Loading