Skip to content

Commit 4462105

Browse files
admin-slushpfalcon
authored andcommitted
binascii: Ported base64 routines for uPy, added unhexlify implementation.
1 parent a1621e9 commit 4462105

File tree

2 files changed

+42
-22
lines changed

2 files changed

+42
-22
lines changed

binascii/binascii.py

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
from pypy.interpreter.error import OperationError
2-
from pypy.interpreter.gateway import unwrap_spec
3-
from rpython.rlib.rstring import StringBuilder
4-
from pypy.module.binascii.interp_binascii import raise_Error
5-
from rpython.rlib.rarithmetic import ovfcheck
1+
from ubinascii import hexlify
2+
3+
def unhexlify(data):
4+
if len(data) % 2 != 0:
5+
raise Exception("Odd-length string")
6+
7+
return b''.join([ int(data[i:i+2], 16).to_bytes(1) for i in range(0, len(data), 2) ])
8+
9+
b2a_hex = hexlify
10+
a2b_hex = unhexlify
611

712
# ____________________________________________________________
813

@@ -34,18 +39,17 @@ def _transform(n):
3439
table_a2b_base64 = ''.join(map(_transform, table_a2b_base64))
3540
assert len(table_a2b_base64) == 256
3641

37-
38-
@unwrap_spec(ascii='bufferstr')
39-
def a2b_base64(space, ascii):
42+
def a2b_base64(ascii):
4043
"Decode a line of base64 data."
4144

42-
res = StringBuilder((len(ascii) // 4) * 3) # maximum estimate
45+
res = []
4346
quad_pos = 0
4447
leftchar = 0
4548
leftbits = 0
4649
last_char_was_a_pad = False
4750

4851
for c in ascii:
52+
c = chr(c)
4953
if c == PAD:
5054
if quad_pos > 2 or (quad_pos == 2 and last_char_was_a_pad):
5155
break # stop on 'xxx=' or on 'xx=='
@@ -63,38 +67,33 @@ def a2b_base64(space, ascii):
6367
#
6468
if leftbits >= 8:
6569
leftbits -= 8
66-
res.append(chr(leftchar >> leftbits))
70+
res.append((leftchar >> leftbits).to_bytes(1))
6771
leftchar &= ((1 << leftbits) - 1)
6872
#
6973
last_char_was_a_pad = False
7074
else:
7175
if leftbits != 0:
72-
raise_Error(space, "Incorrect padding")
76+
raise Exception("Incorrect padding")
7377

74-
return space.wrapbytes(res.build())
78+
return b''.join(res)
7579

7680
# ____________________________________________________________
7781

7882
table_b2a_base64 = (
7983
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
8084

81-
@unwrap_spec(bin='bufferstr')
82-
def b2a_base64(space, bin):
85+
def b2a_base64(bin):
8386
"Base64-code line of data."
8487

8588
newlength = (len(bin) + 2) // 3
86-
try:
87-
newlength = ovfcheck(newlength * 4)
88-
except OverflowError:
89-
raise OperationError(space.w_MemoryError, space.w_None)
90-
newlength += 1
91-
res = StringBuilder(newlength)
89+
newlength = newlength * 4 + 1
90+
res = []
9291

9392
leftchar = 0
9493
leftbits = 0
9594
for c in bin:
9695
# Shift into our buffer, and output any 6bits ready
97-
leftchar = (leftchar << 8) | ord(c)
96+
leftchar = (leftchar << 8) | c
9897
leftbits += 8
9998
res.append(table_b2a_base64[(leftchar >> (leftbits-6)) & 0x3f])
10099
leftbits -= 6
@@ -110,4 +109,4 @@ def b2a_base64(space, bin):
110109
res.append(table_b2a_base64[(leftchar & 0xf) << 2])
111110
res.append(PAD)
112111
res.append('\n')
113-
return space.wrapbytes(res.build())
112+
return ''.join(res).encode('ascii')

binascii/test_binascii.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from binascii import hexlify, unhexlify
2+
import utime
3+
4+
data = b'zlutoucky kun upel dabelske ody'
5+
h = hexlify(data)
6+
7+
if h != b'7a6c75746f75636b79206b756e207570656c20646162656c736b65206f6479':
8+
raise Exception("Error")
9+
10+
data2 = unhexlify(h)
11+
12+
if data2 != data:
13+
raise Exception("Error")
14+
15+
start = utime.time()
16+
for x in range(100000):
17+
d = unhexlify(h)
18+
19+
print("100000 iterations in: " + str(utime.time() - start))
20+
21+
print("OK")

0 commit comments

Comments
 (0)