mirror of
https://github.com/bazel-contrib/bazel-lib
synced 2024-11-25 11:32:33 +00:00
869 lines
14 KiB
Python
869 lines
14 KiB
Python
"""Base64 encoder/decoder utility for Starlark
|
|
|
|
Handles string only and not binary data
|
|
|
|
Implementation based on https://gist.github.com/trondhumbor/ce57c0c2816bb45a8fbb but adapted to use
|
|
the subset of python available in Starlark.
|
|
"""
|
|
|
|
def decode(data):
|
|
"""Decode a Base64 encoded string.
|
|
|
|
See https://en.wikipedia.org/wiki/Base64.
|
|
|
|
Args:
|
|
data: base64 encoded string
|
|
|
|
Returns:
|
|
A string containing the decoded data
|
|
"""
|
|
padding = data.count("=")
|
|
data = data.replace("=", "A")
|
|
|
|
binstring = ""
|
|
for i in range(len(data)):
|
|
index = BASE64_CHARS.find(data[i])
|
|
if index == -1:
|
|
fail("expected a base64 encoded string")
|
|
binstring += _int_to_binary(index, 6)
|
|
|
|
eight_chunks = _chunk(binstring, 8)
|
|
|
|
outstring = ""
|
|
for chunk in eight_chunks:
|
|
outstring += _int_to_char(int(chunk, 2))
|
|
|
|
return outstring if padding == 0 else outstring[:-padding]
|
|
|
|
def encode(data):
|
|
"""Base64 encode a string.
|
|
|
|
See https://en.wikipedia.org/wiki/Base64.
|
|
|
|
Args:
|
|
data: string to encode
|
|
|
|
Returns:
|
|
The base64 encoded string
|
|
"""
|
|
padding = 0
|
|
if len(data) % 3 != 0:
|
|
padding = (len(data) + 3 - len(data) % 3) - len(data)
|
|
data += "\0" * padding
|
|
|
|
three_chunks = _chunk(data, 3)
|
|
|
|
binstring = ""
|
|
for chunk in three_chunks:
|
|
for i in range(len(chunk)):
|
|
binstring += _int_to_binary(_char_to_int(chunk[i]))
|
|
|
|
six_chunks = _chunk(binstring, 6)
|
|
|
|
outstring = ""
|
|
for element in six_chunks:
|
|
outstring += BASE64_CHARS[int(element, 2)]
|
|
|
|
return outstring if padding == 0 else outstring[:-padding] + "=" * padding
|
|
|
|
def _char_to_int(c):
|
|
if len(c) != 1:
|
|
fail("expected a string with a single character")
|
|
return CHAR_TO_INT.get(c)
|
|
|
|
def _int_to_binary(i, digits = 8):
|
|
if i < 0 or i > 255:
|
|
fail("expected a int between 0 and 255 (inclusive)")
|
|
if digits < 1 or digits > 8:
|
|
fail("expected digits to be between 1 and 8 (inclusive)")
|
|
return INT_TO_BINARY[i][8 - digits:]
|
|
|
|
def _int_to_char(i):
|
|
if i < 0 or i > 255:
|
|
fail("expected a int between 0 and 255 (inclusive)")
|
|
return INT_TO_CHAR[i]
|
|
|
|
def _chunk(data, length):
|
|
return [data[i:i + length] for i in range(0, len(data), length)]
|
|
|
|
BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
|
|
|
# Starlark support octal values that we can leverage for this conversion.
|
|
# Generated by lib/private/base64.py utility script.
|
|
CHAR_TO_INT = {
|
|
"\0": 0,
|
|
"\1": 1,
|
|
"\2": 2,
|
|
"\3": 3,
|
|
"\4": 4,
|
|
"\5": 5,
|
|
"\6": 6,
|
|
"\7": 7,
|
|
"\10": 8,
|
|
"\11": 9,
|
|
"\12": 10,
|
|
"\13": 11,
|
|
"\14": 12,
|
|
"\15": 13,
|
|
"\16": 14,
|
|
"\17": 15,
|
|
"\20": 16,
|
|
"\21": 17,
|
|
"\22": 18,
|
|
"\23": 19,
|
|
"\24": 20,
|
|
"\25": 21,
|
|
"\26": 22,
|
|
"\27": 23,
|
|
"\30": 24,
|
|
"\31": 25,
|
|
"\32": 26,
|
|
"\33": 27,
|
|
"\34": 28,
|
|
"\35": 29,
|
|
"\36": 30,
|
|
"\37": 31,
|
|
"\40": 32,
|
|
"\41": 33,
|
|
"\42": 34,
|
|
"\43": 35,
|
|
"\44": 36,
|
|
"\45": 37,
|
|
"\46": 38,
|
|
"\47": 39,
|
|
"\50": 40,
|
|
"\51": 41,
|
|
"\52": 42,
|
|
"\53": 43,
|
|
"\54": 44,
|
|
"\55": 45,
|
|
"\56": 46,
|
|
"\57": 47,
|
|
"\60": 48,
|
|
"\61": 49,
|
|
"\62": 50,
|
|
"\63": 51,
|
|
"\64": 52,
|
|
"\65": 53,
|
|
"\66": 54,
|
|
"\67": 55,
|
|
"\70": 56,
|
|
"\71": 57,
|
|
"\72": 58,
|
|
"\73": 59,
|
|
"\74": 60,
|
|
"\75": 61,
|
|
"\76": 62,
|
|
"\77": 63,
|
|
"\100": 64,
|
|
"\101": 65,
|
|
"\102": 66,
|
|
"\103": 67,
|
|
"\104": 68,
|
|
"\105": 69,
|
|
"\106": 70,
|
|
"\107": 71,
|
|
"\110": 72,
|
|
"\111": 73,
|
|
"\112": 74,
|
|
"\113": 75,
|
|
"\114": 76,
|
|
"\115": 77,
|
|
"\116": 78,
|
|
"\117": 79,
|
|
"\120": 80,
|
|
"\121": 81,
|
|
"\122": 82,
|
|
"\123": 83,
|
|
"\124": 84,
|
|
"\125": 85,
|
|
"\126": 86,
|
|
"\127": 87,
|
|
"\130": 88,
|
|
"\131": 89,
|
|
"\132": 90,
|
|
"\133": 91,
|
|
"\134": 92,
|
|
"\135": 93,
|
|
"\136": 94,
|
|
"\137": 95,
|
|
"\140": 96,
|
|
"\141": 97,
|
|
"\142": 98,
|
|
"\143": 99,
|
|
"\144": 100,
|
|
"\145": 101,
|
|
"\146": 102,
|
|
"\147": 103,
|
|
"\150": 104,
|
|
"\151": 105,
|
|
"\152": 106,
|
|
"\153": 107,
|
|
"\154": 108,
|
|
"\155": 109,
|
|
"\156": 110,
|
|
"\157": 111,
|
|
"\160": 112,
|
|
"\161": 113,
|
|
"\162": 114,
|
|
"\163": 115,
|
|
"\164": 116,
|
|
"\165": 117,
|
|
"\166": 118,
|
|
"\167": 119,
|
|
"\170": 120,
|
|
"\171": 121,
|
|
"\172": 122,
|
|
"\173": 123,
|
|
"\174": 124,
|
|
"\175": 125,
|
|
"\176": 126,
|
|
"\177": 127,
|
|
"\200": 128,
|
|
"\201": 129,
|
|
"\202": 130,
|
|
"\203": 131,
|
|
"\204": 132,
|
|
"\205": 133,
|
|
"\206": 134,
|
|
"\207": 135,
|
|
"\210": 136,
|
|
"\211": 137,
|
|
"\212": 138,
|
|
"\213": 139,
|
|
"\214": 140,
|
|
"\215": 141,
|
|
"\216": 142,
|
|
"\217": 143,
|
|
"\220": 144,
|
|
"\221": 145,
|
|
"\222": 146,
|
|
"\223": 147,
|
|
"\224": 148,
|
|
"\225": 149,
|
|
"\226": 150,
|
|
"\227": 151,
|
|
"\230": 152,
|
|
"\231": 153,
|
|
"\232": 154,
|
|
"\233": 155,
|
|
"\234": 156,
|
|
"\235": 157,
|
|
"\236": 158,
|
|
"\237": 159,
|
|
"\240": 160,
|
|
"\241": 161,
|
|
"\242": 162,
|
|
"\243": 163,
|
|
"\244": 164,
|
|
"\245": 165,
|
|
"\246": 166,
|
|
"\247": 167,
|
|
"\250": 168,
|
|
"\251": 169,
|
|
"\252": 170,
|
|
"\253": 171,
|
|
"\254": 172,
|
|
"\255": 173,
|
|
"\256": 174,
|
|
"\257": 175,
|
|
"\260": 176,
|
|
"\261": 177,
|
|
"\262": 178,
|
|
"\263": 179,
|
|
"\264": 180,
|
|
"\265": 181,
|
|
"\266": 182,
|
|
"\267": 183,
|
|
"\270": 184,
|
|
"\271": 185,
|
|
"\272": 186,
|
|
"\273": 187,
|
|
"\274": 188,
|
|
"\275": 189,
|
|
"\276": 190,
|
|
"\277": 191,
|
|
"\300": 192,
|
|
"\301": 193,
|
|
"\302": 194,
|
|
"\303": 195,
|
|
"\304": 196,
|
|
"\305": 197,
|
|
"\306": 198,
|
|
"\307": 199,
|
|
"\310": 200,
|
|
"\311": 201,
|
|
"\312": 202,
|
|
"\313": 203,
|
|
"\314": 204,
|
|
"\315": 205,
|
|
"\316": 206,
|
|
"\317": 207,
|
|
"\320": 208,
|
|
"\321": 209,
|
|
"\322": 210,
|
|
"\323": 211,
|
|
"\324": 212,
|
|
"\325": 213,
|
|
"\326": 214,
|
|
"\327": 215,
|
|
"\330": 216,
|
|
"\331": 217,
|
|
"\332": 218,
|
|
"\333": 219,
|
|
"\334": 220,
|
|
"\335": 221,
|
|
"\336": 222,
|
|
"\337": 223,
|
|
"\340": 224,
|
|
"\341": 225,
|
|
"\342": 226,
|
|
"\343": 227,
|
|
"\344": 228,
|
|
"\345": 229,
|
|
"\346": 230,
|
|
"\347": 231,
|
|
"\350": 232,
|
|
"\351": 233,
|
|
"\352": 234,
|
|
"\353": 235,
|
|
"\354": 236,
|
|
"\355": 237,
|
|
"\356": 238,
|
|
"\357": 239,
|
|
"\360": 240,
|
|
"\361": 241,
|
|
"\362": 242,
|
|
"\363": 243,
|
|
"\364": 244,
|
|
"\365": 245,
|
|
"\366": 246,
|
|
"\367": 247,
|
|
"\370": 248,
|
|
"\371": 249,
|
|
"\372": 250,
|
|
"\373": 251,
|
|
"\374": 252,
|
|
"\375": 253,
|
|
"\376": 254,
|
|
"\377": 255,
|
|
}
|
|
|
|
INT_TO_CHAR = [
|
|
"\0",
|
|
"\1",
|
|
"\2",
|
|
"\3",
|
|
"\4",
|
|
"\5",
|
|
"\6",
|
|
"\7",
|
|
"\10",
|
|
"\11",
|
|
"\12",
|
|
"\13",
|
|
"\14",
|
|
"\15",
|
|
"\16",
|
|
"\17",
|
|
"\20",
|
|
"\21",
|
|
"\22",
|
|
"\23",
|
|
"\24",
|
|
"\25",
|
|
"\26",
|
|
"\27",
|
|
"\30",
|
|
"\31",
|
|
"\32",
|
|
"\33",
|
|
"\34",
|
|
"\35",
|
|
"\36",
|
|
"\37",
|
|
"\40",
|
|
"\41",
|
|
"\42",
|
|
"\43",
|
|
"\44",
|
|
"\45",
|
|
"\46",
|
|
"\47",
|
|
"\50",
|
|
"\51",
|
|
"\52",
|
|
"\53",
|
|
"\54",
|
|
"\55",
|
|
"\56",
|
|
"\57",
|
|
"\60",
|
|
"\61",
|
|
"\62",
|
|
"\63",
|
|
"\64",
|
|
"\65",
|
|
"\66",
|
|
"\67",
|
|
"\70",
|
|
"\71",
|
|
"\72",
|
|
"\73",
|
|
"\74",
|
|
"\75",
|
|
"\76",
|
|
"\77",
|
|
"\100",
|
|
"\101",
|
|
"\102",
|
|
"\103",
|
|
"\104",
|
|
"\105",
|
|
"\106",
|
|
"\107",
|
|
"\110",
|
|
"\111",
|
|
"\112",
|
|
"\113",
|
|
"\114",
|
|
"\115",
|
|
"\116",
|
|
"\117",
|
|
"\120",
|
|
"\121",
|
|
"\122",
|
|
"\123",
|
|
"\124",
|
|
"\125",
|
|
"\126",
|
|
"\127",
|
|
"\130",
|
|
"\131",
|
|
"\132",
|
|
"\133",
|
|
"\134",
|
|
"\135",
|
|
"\136",
|
|
"\137",
|
|
"\140",
|
|
"\141",
|
|
"\142",
|
|
"\143",
|
|
"\144",
|
|
"\145",
|
|
"\146",
|
|
"\147",
|
|
"\150",
|
|
"\151",
|
|
"\152",
|
|
"\153",
|
|
"\154",
|
|
"\155",
|
|
"\156",
|
|
"\157",
|
|
"\160",
|
|
"\161",
|
|
"\162",
|
|
"\163",
|
|
"\164",
|
|
"\165",
|
|
"\166",
|
|
"\167",
|
|
"\170",
|
|
"\171",
|
|
"\172",
|
|
"\173",
|
|
"\174",
|
|
"\175",
|
|
"\176",
|
|
"\177",
|
|
"\200",
|
|
"\201",
|
|
"\202",
|
|
"\203",
|
|
"\204",
|
|
"\205",
|
|
"\206",
|
|
"\207",
|
|
"\210",
|
|
"\211",
|
|
"\212",
|
|
"\213",
|
|
"\214",
|
|
"\215",
|
|
"\216",
|
|
"\217",
|
|
"\220",
|
|
"\221",
|
|
"\222",
|
|
"\223",
|
|
"\224",
|
|
"\225",
|
|
"\226",
|
|
"\227",
|
|
"\230",
|
|
"\231",
|
|
"\232",
|
|
"\233",
|
|
"\234",
|
|
"\235",
|
|
"\236",
|
|
"\237",
|
|
"\240",
|
|
"\241",
|
|
"\242",
|
|
"\243",
|
|
"\244",
|
|
"\245",
|
|
"\246",
|
|
"\247",
|
|
"\250",
|
|
"\251",
|
|
"\252",
|
|
"\253",
|
|
"\254",
|
|
"\255",
|
|
"\256",
|
|
"\257",
|
|
"\260",
|
|
"\261",
|
|
"\262",
|
|
"\263",
|
|
"\264",
|
|
"\265",
|
|
"\266",
|
|
"\267",
|
|
"\270",
|
|
"\271",
|
|
"\272",
|
|
"\273",
|
|
"\274",
|
|
"\275",
|
|
"\276",
|
|
"\277",
|
|
"\300",
|
|
"\301",
|
|
"\302",
|
|
"\303",
|
|
"\304",
|
|
"\305",
|
|
"\306",
|
|
"\307",
|
|
"\310",
|
|
"\311",
|
|
"\312",
|
|
"\313",
|
|
"\314",
|
|
"\315",
|
|
"\316",
|
|
"\317",
|
|
"\320",
|
|
"\321",
|
|
"\322",
|
|
"\323",
|
|
"\324",
|
|
"\325",
|
|
"\326",
|
|
"\327",
|
|
"\330",
|
|
"\331",
|
|
"\332",
|
|
"\333",
|
|
"\334",
|
|
"\335",
|
|
"\336",
|
|
"\337",
|
|
"\340",
|
|
"\341",
|
|
"\342",
|
|
"\343",
|
|
"\344",
|
|
"\345",
|
|
"\346",
|
|
"\347",
|
|
"\350",
|
|
"\351",
|
|
"\352",
|
|
"\353",
|
|
"\354",
|
|
"\355",
|
|
"\356",
|
|
"\357",
|
|
"\360",
|
|
"\361",
|
|
"\362",
|
|
"\363",
|
|
"\364",
|
|
"\365",
|
|
"\366",
|
|
"\367",
|
|
"\370",
|
|
"\371",
|
|
"\372",
|
|
"\373",
|
|
"\374",
|
|
"\375",
|
|
"\376",
|
|
"\377",
|
|
]
|
|
|
|
INT_TO_BINARY = [
|
|
"00000000",
|
|
"00000001",
|
|
"00000010",
|
|
"00000011",
|
|
"00000100",
|
|
"00000101",
|
|
"00000110",
|
|
"00000111",
|
|
"00001000",
|
|
"00001001",
|
|
"00001010",
|
|
"00001011",
|
|
"00001100",
|
|
"00001101",
|
|
"00001110",
|
|
"00001111",
|
|
"00010000",
|
|
"00010001",
|
|
"00010010",
|
|
"00010011",
|
|
"00010100",
|
|
"00010101",
|
|
"00010110",
|
|
"00010111",
|
|
"00011000",
|
|
"00011001",
|
|
"00011010",
|
|
"00011011",
|
|
"00011100",
|
|
"00011101",
|
|
"00011110",
|
|
"00011111",
|
|
"00100000",
|
|
"00100001",
|
|
"00100010",
|
|
"00100011",
|
|
"00100100",
|
|
"00100101",
|
|
"00100110",
|
|
"00100111",
|
|
"00101000",
|
|
"00101001",
|
|
"00101010",
|
|
"00101011",
|
|
"00101100",
|
|
"00101101",
|
|
"00101110",
|
|
"00101111",
|
|
"00110000",
|
|
"00110001",
|
|
"00110010",
|
|
"00110011",
|
|
"00110100",
|
|
"00110101",
|
|
"00110110",
|
|
"00110111",
|
|
"00111000",
|
|
"00111001",
|
|
"00111010",
|
|
"00111011",
|
|
"00111100",
|
|
"00111101",
|
|
"00111110",
|
|
"00111111",
|
|
"01000000",
|
|
"01000001",
|
|
"01000010",
|
|
"01000011",
|
|
"01000100",
|
|
"01000101",
|
|
"01000110",
|
|
"01000111",
|
|
"01001000",
|
|
"01001001",
|
|
"01001010",
|
|
"01001011",
|
|
"01001100",
|
|
"01001101",
|
|
"01001110",
|
|
"01001111",
|
|
"01010000",
|
|
"01010001",
|
|
"01010010",
|
|
"01010011",
|
|
"01010100",
|
|
"01010101",
|
|
"01010110",
|
|
"01010111",
|
|
"01011000",
|
|
"01011001",
|
|
"01011010",
|
|
"01011011",
|
|
"01011100",
|
|
"01011101",
|
|
"01011110",
|
|
"01011111",
|
|
"01100000",
|
|
"01100001",
|
|
"01100010",
|
|
"01100011",
|
|
"01100100",
|
|
"01100101",
|
|
"01100110",
|
|
"01100111",
|
|
"01101000",
|
|
"01101001",
|
|
"01101010",
|
|
"01101011",
|
|
"01101100",
|
|
"01101101",
|
|
"01101110",
|
|
"01101111",
|
|
"01110000",
|
|
"01110001",
|
|
"01110010",
|
|
"01110011",
|
|
"01110100",
|
|
"01110101",
|
|
"01110110",
|
|
"01110111",
|
|
"01111000",
|
|
"01111001",
|
|
"01111010",
|
|
"01111011",
|
|
"01111100",
|
|
"01111101",
|
|
"01111110",
|
|
"01111111",
|
|
"10000000",
|
|
"10000001",
|
|
"10000010",
|
|
"10000011",
|
|
"10000100",
|
|
"10000101",
|
|
"10000110",
|
|
"10000111",
|
|
"10001000",
|
|
"10001001",
|
|
"10001010",
|
|
"10001011",
|
|
"10001100",
|
|
"10001101",
|
|
"10001110",
|
|
"10001111",
|
|
"10010000",
|
|
"10010001",
|
|
"10010010",
|
|
"10010011",
|
|
"10010100",
|
|
"10010101",
|
|
"10010110",
|
|
"10010111",
|
|
"10011000",
|
|
"10011001",
|
|
"10011010",
|
|
"10011011",
|
|
"10011100",
|
|
"10011101",
|
|
"10011110",
|
|
"10011111",
|
|
"10100000",
|
|
"10100001",
|
|
"10100010",
|
|
"10100011",
|
|
"10100100",
|
|
"10100101",
|
|
"10100110",
|
|
"10100111",
|
|
"10101000",
|
|
"10101001",
|
|
"10101010",
|
|
"10101011",
|
|
"10101100",
|
|
"10101101",
|
|
"10101110",
|
|
"10101111",
|
|
"10110000",
|
|
"10110001",
|
|
"10110010",
|
|
"10110011",
|
|
"10110100",
|
|
"10110101",
|
|
"10110110",
|
|
"10110111",
|
|
"10111000",
|
|
"10111001",
|
|
"10111010",
|
|
"10111011",
|
|
"10111100",
|
|
"10111101",
|
|
"10111110",
|
|
"10111111",
|
|
"11000000",
|
|
"11000001",
|
|
"11000010",
|
|
"11000011",
|
|
"11000100",
|
|
"11000101",
|
|
"11000110",
|
|
"11000111",
|
|
"11001000",
|
|
"11001001",
|
|
"11001010",
|
|
"11001011",
|
|
"11001100",
|
|
"11001101",
|
|
"11001110",
|
|
"11001111",
|
|
"11010000",
|
|
"11010001",
|
|
"11010010",
|
|
"11010011",
|
|
"11010100",
|
|
"11010101",
|
|
"11010110",
|
|
"11010111",
|
|
"11011000",
|
|
"11011001",
|
|
"11011010",
|
|
"11011011",
|
|
"11011100",
|
|
"11011101",
|
|
"11011110",
|
|
"11011111",
|
|
"11100000",
|
|
"11100001",
|
|
"11100010",
|
|
"11100011",
|
|
"11100100",
|
|
"11100101",
|
|
"11100110",
|
|
"11100111",
|
|
"11101000",
|
|
"11101001",
|
|
"11101010",
|
|
"11101011",
|
|
"11101100",
|
|
"11101101",
|
|
"11101110",
|
|
"11101111",
|
|
"11110000",
|
|
"11110001",
|
|
"11110010",
|
|
"11110011",
|
|
"11110100",
|
|
"11110101",
|
|
"11110110",
|
|
"11110111",
|
|
"11111000",
|
|
"11111001",
|
|
"11111010",
|
|
"11111011",
|
|
"11111100",
|
|
"11111101",
|
|
"11111110",
|
|
"11111111",
|
|
]
|