Quick actions

cmd+k|ctrl+k

Navigation

Languages

base64 encoder

Snippet info

Language

Python

Visibility

public

Author

jack98765.2007

Created

2024-01-16T16:34:43.693959Z

Updated

2024-01-19T10:36:06.635107Z

# 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")}')
    
INFO