# base64 encoder
def b64encode(data, /, encoding='utf-8', mode='default'):
alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
if mode == 'default':
alphabet += '+/'
padding = '='
elif mode == 'urlsafe':
alphabet += '-_'
padding = '='
else:
raise ValueError("mode must be either 'default' or 'urlsafe'")
if isinstance(data, bytes):
return _b64encode(data, alphabet, padding)
elif isinstance(data, str):
return _b64encode(bytes(data, encoding), alphabet, padding)
else:
raise TypeError('1st argument type must be str or bytes')
def _b64encode(data, alphabet, padding):
rest = data[: 3 * (len(data) // 3)]
last = data[3 * (len(data) // 3) : len(data)]
return _b64encode_rest(rest, alphabet) + _b64encode_last(last, alphabet, padding)
def _b64encode_rest(data, alphabet):
# group 3 bytes into 24-bit ints
data_24bit = []
for i in range(0, len(data), 3):
byte0, byte1, byte2 = data[i:i+3]
data_24bit.append((byte0 << 16) + (byte1 << 8) + byte2)
# split 24-bit ints into 6-bit (base64) ints using bit masking
data_6bit = []
for d24 in data_24bit:
int0 = (d24 & 0b111111 << 18) >> 18
int1 = (d24 & 0b111111 << 12) >> 12
int2 = (d24 & 0b111111 << 6) >> 6
int3 = d24 & 0b111111
data_6bit += [int0, int1, int2, int3]
# map each base64 int to the base64 encoding
return ''.join(alphabet[d6] for d6 in data_6bit)
def _b64encode_last(data, alphabet, padding):
if len(data) == 0:
return ''
elif len(data) == 1:
# split byte into a 6-bit int and a padded 6-bit int
int0 = (data[0] & 0b11111100) >> 2
int1 = (data[0] & 0b00000011) << 4
return alphabet[int0] + alphabet[int1] + padding * 2
elif len(data) == 2:
# similar to above
data_16bit = data[0] << 8 + data[1]
int0 = (data_16bit & 0b111111 << 10) >> 10
int1 = (data_16bit & 0b111111 << 4) >> 4
int2 = data_16bit & 0b001111 << 2
return alphabet[int0] + alphabet[int1] + alphabet[int2] + padding
if __name__ == '__main__':
inpt = input()
print(f'standard b64: {b64encode(inpt)}')
print(f'urlsafe b64: {b64encode(inpt, mode="urlsafe")}')