mirror of
https://github.com/NixOS/nix.git
synced 2025-11-15 23:12:44 +01:00
Clean up Base* code
Make it separate from Hash, since other things can be base-encoded too. This isn't really needed for Nix, but it makes the code easier to read e.g. for someone reimplementing this stuff in a different language. (Of course, Base16/Base64 should be gotten off-the-shelf, but now the hash code, which is more bespoke, is less cluttered with the parts that would be from some library.) Many reimplementations of "Nix32" and our hash type already exist, so this cleanup is coming years too late, but I say better late than never / it is always good to nudge the code in the direction of being a "living spec". Co-authored-by: Sergei Zimmerman <sergei@zimmerman.foo>
This commit is contained in:
parent
664f06c94c
commit
991831227e
18 changed files with 357 additions and 244 deletions
|
|
@ -1,6 +1,7 @@
|
|||
#include <cassert>
|
||||
|
||||
#include "nix/util/base-nix-32.hh"
|
||||
#include "nix/util/util.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
|
@ -16,12 +17,12 @@ constexpr const std::array<unsigned char, 256> BaseNix32::reverseMap = [] {
|
|||
return map;
|
||||
}();
|
||||
|
||||
std::string BaseNix32::encode(std::span<const uint8_t> originalData)
|
||||
std::string BaseNix32::encode(std::span<const std::byte> bs)
|
||||
{
|
||||
if (originalData.size() == 0)
|
||||
if (bs.size() == 0)
|
||||
return {};
|
||||
|
||||
size_t len = encodedLength(originalData.size());
|
||||
size_t len = encodedLength(bs.size());
|
||||
assert(len);
|
||||
|
||||
std::string s;
|
||||
|
|
@ -31,12 +32,42 @@ std::string BaseNix32::encode(std::span<const uint8_t> originalData)
|
|||
unsigned int b = n * 5;
|
||||
unsigned int i = b / 8;
|
||||
unsigned int j = b % 8;
|
||||
unsigned char c =
|
||||
(originalData.data()[i] >> j) | (i >= originalData.size() - 1 ? 0 : originalData.data()[i + 1] << (8 - j));
|
||||
s.push_back(characters[c & 0x1f]);
|
||||
std::byte c = (bs.data()[i] >> j) | (i >= bs.size() - 1 ? std::byte{0} : bs.data()[i + 1] << (8 - j));
|
||||
s.push_back(characters[uint8_t(c & std::byte{0x1f})]);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string BaseNix32::decode(std::string_view s)
|
||||
{
|
||||
std::string res;
|
||||
res.reserve((s.size() * 5 + 7) / 8); // ceiling(size * 5/8)
|
||||
|
||||
for (unsigned int n = 0; n < s.size(); ++n) {
|
||||
char c = s[s.size() - n - 1];
|
||||
auto digit_opt = BaseNix32::lookupReverse(c);
|
||||
|
||||
if (!digit_opt)
|
||||
throw FormatError("invalid character in Nix32 (Nix's Base32 variation) string: '%c'", c);
|
||||
|
||||
uint8_t digit = *digit_opt;
|
||||
|
||||
unsigned int b = n * 5;
|
||||
unsigned int i = b / 8;
|
||||
unsigned int j = b % 8;
|
||||
|
||||
// Ensure res has enough space
|
||||
res.resize(i + 1);
|
||||
res[i] |= digit << j;
|
||||
|
||||
if (digit >> (8 - j)) {
|
||||
res.resize(i + 2);
|
||||
res[i + 1] |= digit >> (8 - j);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace nix
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue