impl/python/base64_encode.py
1,327 bytes · the Python implementation · view raw
from typing import Sequence
_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
def base64_encode(bytes: Sequence[int]) -> str:
"""Bytes as standard base64 (RFC 4648 section 4), padded with "=".
A Python ``bytes`` value is accepted as is; a list must hold integers
0-255, and anything else is refused rather than masked to a byte.
"""
if isinstance(bytes, (str, dict)) or not hasattr(bytes, "__len__"):
raise TypeError("bytes must be a list of integers from 0 to 255")
for b in bytes:
if type(b) is not int or b < 0 or b > 255:
raise ValueError("bytes must be a list of integers from 0 to 255")
out = []
n_full = len(bytes) - len(bytes) % 3
for i in range(0, n_full, 3):
n = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]
out.append(_ALPHABET[(n >> 18) & 63] + _ALPHABET[(n >> 12) & 63] + _ALPHABET[(n >> 6) & 63] + _ALPHABET[n & 63])
rest = len(bytes) - n_full
if rest == 1:
n = bytes[n_full] << 16
out.append(_ALPHABET[(n >> 18) & 63] + _ALPHABET[(n >> 12) & 63] + "==")
elif rest == 2:
n = (bytes[n_full] << 16) | (bytes[n_full + 1] << 8)
out.append(_ALPHABET[(n >> 18) & 63] + _ALPHABET[(n >> 12) & 63] + _ALPHABET[(n >> 6) & 63] + "=")
return "".join(out)