1# No unicode_literals
2import json
3import os
4import unicodedata
5from binascii import hexlify, unhexlify
6from hkdf import Hkdf
7
8
9def HKDF(skm, outlen, salt=None, CTXinfo=b""):
10    return Hkdf(salt, skm).expand(CTXinfo, outlen)
11
12def to_bytes(u):
13    return unicodedata.normalize("NFC", u).encode("utf-8")
14
15def to_unicode(any):
16    if isinstance(any, type(u"")):
17        return any
18    return any.decode("ascii")
19
20def bytes_to_hexstr(b):
21    assert isinstance(b, type(b""))
22    hexstr = hexlify(b).decode("ascii")
23    assert isinstance(hexstr, type(u""))
24    return hexstr
25
26
27def hexstr_to_bytes(hexstr):
28    assert isinstance(hexstr, type(u""))
29    b = unhexlify(hexstr.encode("ascii"))
30    assert isinstance(b, type(b""))
31    return b
32
33
34def dict_to_bytes(d):
35    assert isinstance(d, dict)
36    b = json.dumps(d).encode("utf-8")
37    assert isinstance(b, type(b""))
38    return b
39
40
41def bytes_to_dict(b):
42    assert isinstance(b, type(b""))
43    d = json.loads(b.decode("utf-8"))
44    assert isinstance(d, dict)
45    return d
46
47
48def estimate_free_space(target):
49    # f_bfree is the blocks available to a root user. It might be more
50    # accurate to use f_bavail (blocks available to non-root user), but we
51    # don't know which user is running us, and a lot of installations don't
52    # bother with reserving extra space for root, so let's just stick to the
53    # basic (larger) estimate.
54    try:
55        s = os.statvfs(os.path.dirname(os.path.abspath(target)))
56        return s.f_frsize * s.f_bfree
57    except AttributeError:
58        return None
59