1from time import time
2
3from bitarray import bitarray, get_default_endian
4from bitarray.util import urandom, ba2hex, hex2ba, ba2base, base2ba
5
6
7# ----- conversion using prefix codes
8
9CODEDICT = {'little': {}, 'big': {
10    '0': bitarray('0000'),    '1': bitarray('0001'),
11    '2': bitarray('0010'),    '3': bitarray('0011'),
12    '4': bitarray('0100'),    '5': bitarray('0101'),
13    '6': bitarray('0110'),    '7': bitarray('0111'),
14    '8': bitarray('1000'),    '9': bitarray('1001'),
15    'a': bitarray('1010'),    'b': bitarray('1011'),
16    'c': bitarray('1100'),    'd': bitarray('1101'),
17    'e': bitarray('1110'),    'f': bitarray('1111'),
18}}
19for k, v in CODEDICT['big'].items(): # type: ignore
20    CODEDICT['little'][k] = v[::-1]  # type: ignore
21
22def prefix_ba2hex(a):
23    return ''.join(a.iterdecode(CODEDICT[a.endian()]))
24
25def prefix_hex2ba(s, endian=None):
26    a = bitarray(0, endian or get_default_endian())
27    a.encode(CODEDICT[a.endian()], s)
28    return a
29
30# ----- conversion using ba2base (element based utility function)
31
32def ba2_base16(a):
33    return ba2base(16, a)
34
35def base16_2ba(s, endian=None):
36    return base2ba(16, s, endian)
37
38# ----- test
39
40def test_round(f, g, n, endian):
41    # f: function which takes bitarray and returns hexstr
42    # g: function which takes hexstr and returns bitarray
43    # n: size of random bitarray
44    a = urandom(n, endian)
45    t0 = time()
46    s = f(a)
47    print('%s:  %9.6f sec' % (f.__name__, time() - t0))
48    t0 = time()
49    b = g(s, endian)
50    print('%s:  %9.6f sec' % (g.__name__, time() - t0))
51    assert b == a
52
53if __name__ == '__main__':
54    n = 100 * 1000 * 1000 + 4
55    for endian in 'little', 'big':
56        print('%s-endian:' % endian)
57        for f in ba2hex, ba2_base16, prefix_ba2hex:
58            for g in hex2ba, base16_2ba, prefix_hex2ba:
59                test_round(f, g, n, endian)
60            print()
61