Skip to main content

Hexahexacontadecimal

The most compact way to encode a number into a URL.

Hexahexacontadecimal is a compact format to express a number or binary data in a URL. It uses all characters allowed in a URL – the unreserved characters – making it the most concise way to express a positive integer in a URL.

Note that urllib.quote escapes the tilde character (~), which is not necessary as of RFC3986, so if you use this on HHC data you’ll waste bytes. Use the provided hhc_url_quote function instead if you must. By definition though HHC values don’t need any URL quoting.

Usage

>>> from hexahexacontadecimal import hhc, hhc_to_int
>>> print(hhc(302231454903657293676544))
iFsGUkO.0tsxw
>>> print(hhc_to_int('iFsGUkO.0tsxw'))
302231454903657293676544

Hexahexacontadecimal vs Base64 in URLs

>>> n = 292231454903657293676544
>>> import base64
>>> print(hhc_url_quote(base64.urlsafe_b64encode(long_to_binary(n))))
PeHmHzZFTcAAAA%3D%3D
>>> print(hhc_url_quote(hhc(n)))
gpE4Xoy7fw5AO

Base64 vs HHC in a bad case for Base64:

>>> n = 64 ** 5 + 1
>>> print(hhc_url_quote(base64.urlsafe_b64encode(long_to_binary(n))))
QAAAAQ%3D%3D
>>> print(hhc(n))
ucrDZ

Base64 vs HHC in a bad case for HHC:

>>> n = 66 ** 5 + 1
>>> print(hhc_url_quote(base64.urlsafe_b64encode(long_to_binary(n))))
SqUUIQ%3D%3D
>>> print(hhc(n))
100001

That big SHA-512 you always wanted to write in a URL:

>>> n = 2 ** 512
>>> print(hhc_url_quote(base64.urlsafe_b64encode(long_to_binary(n))))
AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%3D
>>> print(hhc(n))
JK84xqGD9FMXPNubPghADlRhBUzlqRscC2h~8xmi99PvuQsUCIB2CHGhMUQR8FLm72.Hbbctkqi89xspay~y4

Massive savings!

Are the savings really significant?

If you’re currently doing your Base64 encoding the naive way, then yes. Encoding all numbers up to 100000, HHC will lead to much shorter total length of URLs.

>>> sum(len(hhc_url_quote(base64.urlsafe_b64encode(long_to_binary(n)))) for n in range(10 ** 5))
531584
>>> sum(len(hhc_url_quote(hhc(n))) for n in range(10 ** 5))
295578

What if I use Base64 without padding?

Then the savings are much less significant. Yet they are still savings. If you’re a perfectionist this is the kind of thing you might care about.

Let’s test it using the code from this StackOverFlow question:

>>> from hexahexacontadecimal.num_encode_base64 import num_encode as num_encode_base64
>>> n = 64 ** 5 + 1
>>> print(hhc_url_quote(num_encode_base64(n)))
BAAAAB
>>> from hexahexacontadecimal.num_encode_base64 import num_decode as num_decode_base64
>>> num_decode_base64(hhc_url_quote(num_encode_base64(n))) == n
True

>>> print(hhc(n))
ucrDZ
>>> hhc_to_int(hhc(n)) == n
True

>>> n = 66 ** 5 + 1
>>> print(hhc_url_quote(num_encode_base64(n)))
BKpRQh
>>> print(hhc_url_quote(hhc(n)))
100001

>>> n = 2 ** 512
>>> hhc_url_quote(num_encode_base64(n))
'EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
>>> print(hhc_url_quote(hhc(n)))
JK84xqGD9FMXPNubPghADlRhBUzlqRscC2h~8xmi99PvuQsUCIB2CHGhMUQR8FLm72.Hbbctkqi89xspay~y4

>>> sum(len(hhc_url_quote(num_encode_base64(n))) for n in range(10 ** 5))
295840
>>> sum(len(hhc_url_quote(hhc(n))) for n in range(10 ** 5))
295578

Why settle for less than perfect?

Sorting

If you wish to be able to sort a list of HHC values numerically there is a variant of HHC that allows this. See sortable_hhc.

>>> hhc(67) < hhc(128)
False
>>> sortable_hhc(67, width=2) < sortable_hhc(128, width=2)
True

Negative Numbers

HHC expresses negative numbers by prefixing the number with , (since minus is taken). This is not a URL safe character so if you URL encode a negative number with HHC you end up with %2C which takes up 2 extra characters. For this reason HHC is not necessarily the shortest representation of a negative number.

The sortable variant also supports negative numbers and will yield the natural sort order (small to large), like -2, -1, 0, 1, 2.

Installation

pip install hexahexacontadecimal

Documentation

This file and docstrings.

Tests

Build Status

To run the unit tests:

nosetests --with-doctest

Changelog

2.2.1

  • Fixed: pandoc accidentally required.

2.2

  • Python 3 support (backwards compatible with Python 2.7).

2.1

  • Fixed: hhc(-1) would cause an infinite loop.

  • New: support for negative values.

2.0

  • New: sortable HHC. This variant of HHC sorts the same alphabetically as numerically for equal length strings.

  • Shorter, more Pythonic method names. The main function is now simply called hhc, styled after Python’s built in hex function. To decode the same, hhc_to_int is now used.

  • import * from hexahexacontadecimal now only imports the main functions.

  • urlquote was renamed to hhc_url_quote to make it easier to differentiate from the standard library method.

1.0

Initial release.

On the command line

With pyle you can easily use hexahexacontadecimal on the command line.

$ wc -c LICENSE MANIFEST setup.py | pyle -m hexahexacontadecimal -e "'%-10s Hexhexconta bytes:' % words[1], hexahexacontadecimal.hhc(int(words[0]))"
LICENSE    Hexhexconta bytes: MV
MANIFEST   Hexhexconta bytes: 1z
setup.py   Hexhexconta bytes: GI
total      Hexhexconta bytes: ei

License

Free to use and modify under the terms of the BSD open source license.

Author

Alexander Ljungberg

Metadata

Release files for hexahexacontadecimal 2.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hexahexacontadecimal 2.2.1
File Size Uploaded Provenance Actions
hexahexacontadecimal-2.2.1.tar.gz 6.5 kB Without provenance Details for hexahexacontadecimal-2.2.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for hexahexacontadecimal 2.2.1
File Interpreter ABI Platform Actions
hexahexacontadecimal-2.2.1-py3-none-any.whl Python 3 none any Details for hexahexacontadecimal-2.2.1-py3-none-any.whl

Total release size: 14.4 kB

Release files / hexahexacontadecimal-2.2.1.tar.gz

Download URL hexahexacontadecimal-2.2.1.tar.gz
Size 6.5 kB
Tags Source
SHA-256 checksum
How to use checksums
7b7567c6d9198ffe01aa144cb31479d06d4b4c51e2d2976a80a35e6a6fd3f8d2
BLAKE2b-256 checksum
How to use checksums
6e49a36173a2f14b8a51331f9527394b112773feee683ef6a5dff4f4091ebcae
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.11.0 pkginfo/1.4.2 requests/2.19.1 setuptools/40.0.0 requests-toolbelt/0.8.0 tqdm/4.24.0 CPython/3.6.4

Release files / hexahexacontadecimal-2.2.1-py3-none-any.whl

Download URL hexahexacontadecimal-2.2.1-py3-none-any.whl
Size 7.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6d0f14b00989014c53e0b8de8e5377b6c2e1da43d943b31652d96ae0a9ef6593
BLAKE2b-256 checksum
How to use checksums
3bab6182b652e1b1f00b54cea12e18e215928c65fa1f9f1e5ed5ba338e7984ea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.11.0 pkginfo/1.4.2 requests/2.19.1 setuptools/40.0.0 requests-toolbelt/0.8.0 tqdm/4.24.0 CPython/3.6.4

Security for hexahexacontadecimal 2.2.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page