Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
37 changes: 28 additions & 9 deletions multibase/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,20 @@

class BaseStringConverter(BaseConverter):
def encode(self, bytes):
# Count leading zero bytes
leading_zeros = 0
for b in bytes:
if b == 0:
leading_zeros += 1
else:
break

number = int.from_bytes(bytes, byteorder="big", signed=False)
return ensure_bytes(super().encode(number))
encoded = ensure_bytes(super().encode(number))

# Prepend the zero-character for each leading zero byte
zero_char = ensure_bytes(self.digits[0])
return zero_char * leading_zeros + encoded

def bytes_to_int(self, bytes):
length = len(bytes)
Expand All @@ -20,11 +32,23 @@ def bytes_to_int(self, bytes):
return value

def decode(self, bytes):
# Count leading zero characters
zero_char = self.digits[0]
leading_zeros = 0

decoded_str = bytes.decode("utf-8") if hasattr(bytes, "decode") else bytes
for ch in decoded_str:
if ch == zero_char:
leading_zeros += 1
else:
break

decoded_int = self.bytes_to_int(bytes)
# See https://docs.python.org/3.5/library/stdtypes.html#int.to_bytes for more about the magical expression
# below
decoded_data = decoded_int.to_bytes((decoded_int.bit_length() + 7) // 8, byteorder="big")
return decoded_data

return b"\x00" * leading_zeros + decoded_data


class Base16StringConverter(BaseStringConverter):
Expand All @@ -39,17 +63,12 @@ def encode(self, bytes):
return ensure_bytes(result)

def decode(self, data):
# Base16 decode is case-insensitive, normalize to our digits case
# Base16 decode is case-insensitive
if isinstance(data, bytes):
data_str = data.decode("utf-8")
else:
data_str = data
# Convert to match our digits case
if self.uppercase:
data_str = data_str.upper()
else:
data_str = data_str.lower()
return super().decode(data_str.encode("utf-8"))
return bytes.fromhex(data_str)


class BaseByteStringConverter:
Expand Down
11 changes: 11 additions & 0 deletions tests/test_multibase.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@
("base64urlpad", "foob", "UZm9vYg=="),
("base64urlpad", "fooba", "UZm9vYmE="),
("base64urlpad", "foobar", "UZm9vYmFy"),
(
"base2",
"\x00\x00yes mani !",
"0001111001011001010111001100100000011011010110000101101110011010010010000000100001",
),
("base8", "\x00\x00yes mani !", "700171312714403326055632220041"),
("base10", "\x00\x00yes mani !", "900573277761329450583662625"),
("base36", "\x00\x00yes mani !", "k002lcpzo5yikidynfl"),
("base32z", "\x00\x00yes mani !", "hyyxf1zgedpcfzg1ebb"),
("base58btc", "\x00\x00yes mani !", "z117paNL19xttacUY"),
("base58flickr", "\x00\x00yes mani !", "Z117Pznk19XTTzBtx"),
)


Expand Down