Skip to content

Commit

Permalink
Add integer support (#12)
Browse files Browse the repository at this point in the history
* Add integer support
* Optimize away slicing in favor of iterator reversed()
  • Loading branch information
LivInTheLookingGlass authored and keis committed Mar 22, 2017
1 parent c5a2f17 commit 3287fcb
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 13 deletions.
40 changes: 28 additions & 12 deletions base58.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,19 @@
buffer = lambda s: s.buffer


def b58encode_int(i, default_one=True):
'''Encode an integer using Base58'''
string = ""
while i:
i, idx = divmod(i, 58)
string = alphabet[idx:idx + 1] + string
if not string and default_one:
string = alphabet[0:1]
return string


def b58encode(v):
'''Encode a string using Base58'''

if not isinstance(v, bytes):
raise TypeError("a bytes-like object is required, not '%s'" %
type(v).__name__)
Expand All @@ -39,16 +49,25 @@ def b58encode(v):
newlen = len(v)

p, acc = 1, 0
for c in iseq(v[::-1]):
for c in iseq(reversed(v)):
acc += p * c
p = p << 8

result = ''
while acc > 0:
acc, mod = divmod(acc, 58)
result += alphabet[mod]
result = b58encode_int(acc, default_one=False)

return (alphabet[0] * (origlen - newlen) + result)

return (result + alphabet[0] * (origlen - newlen))[::-1]

def b58decode_int(v):
'''Decode a Base58 encoded string as an integer'''

if not isinstance(v, str):
v = v.decode('ascii')

decimal = 0
for char in v:
decimal = decimal * 58 + alphabet.index(char)
return decimal


def b58decode(v):
Expand All @@ -61,17 +80,14 @@ def b58decode(v):
v = v.lstrip(alphabet[0])
newlen = len(v)

p, acc = 1, 0
for c in v[::-1]:
acc += p * alphabet.index(c)
p *= 58
acc = b58decode_int(v)

result = []
while acc > 0:
acc, mod = divmod(acc, 256)
result.append(mod)

return (bseq(result) + b'\0' * (origlen - newlen))[::-1]
return (b'\0' * (origlen - newlen) + bseq(reversed(result)))


def b58encode_check(v):
Expand Down
13 changes: 12 additions & 1 deletion test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from contextlib import contextmanager
from itertools import product
from hamcrest import assert_that, equal_to, instance_of
from base58 import b58encode, b58decode, b58encode_check, b58decode_check
from base58 import b58encode, b58decode, b58encode_check, b58decode_check, b58encode_int, b58decode_int, alphabet


class RaisesContext(object):
Expand Down Expand Up @@ -83,3 +83,14 @@ def test_input_should_be_bytes():
data = u'3vQB7B6MrGQZaxCuFg4oH'
with assert_raises(TypeError):
b58encode(data)


def test_simple_integers():
for idx, char in enumerate(alphabet):
assert_that(b58decode_int(char), equal_to(idx))
assert_that(b58encode_int(idx), equal_to(char))

def test_large_integer():
number = 0x111d38e5fc9071ffcd20b4a763cc9ae4f252bb4e48fd66a835e252ada93ff480d6dd43dc62a641155a5
assert_that(b58decode_int(alphabet), equal_to(number))
assert_that(b58encode_int(number), equal_to(alphabet[1:]))

0 comments on commit 3287fcb

Please sign in to comment.