106 lines
2.8 KiB
Python
106 lines
2.8 KiB
Python
"""
|
|
Implementation of Base122 in pure Python.
|
|
It attempts to mirror behaviour of the base64 built-in module.
|
|
|
|
Its API is not yet complete or final. This is a first version for testing.
|
|
"""
|
|
|
|
illegals = [0, 10, 13, 34, 38, 92]
|
|
|
|
def b122encode(raw_data):
|
|
if isinstance(raw_data, str):
|
|
raise ValueError("Input should be bytes")
|
|
|
|
out_data = []
|
|
cur_index = 0
|
|
cur_bit = 0
|
|
|
|
def get_7():
|
|
nonlocal cur_index, cur_bit
|
|
if cur_index >= len(raw_data):
|
|
return False
|
|
|
|
first_byte = raw_data[cur_index]
|
|
first_part = ((0b11111110 >> cur_bit) & first_byte) << cur_bit
|
|
first_part >>= 1
|
|
|
|
cur_bit += 7
|
|
if cur_bit < 8:
|
|
return first_part
|
|
|
|
cur_bit -= 8
|
|
cur_index += 1
|
|
|
|
if cur_index >= len(raw_data):
|
|
return first_part
|
|
|
|
second_byte = raw_data[cur_index]
|
|
second_part = ((0xFF00 >> cur_bit) & second_byte) & 0xFF
|
|
second_part >>= 8 - cur_bit
|
|
return first_part | second_part
|
|
|
|
while True:
|
|
bits = get_7()
|
|
if bits is False:
|
|
break
|
|
|
|
illegal_index = illegals.index(bits) if bits in illegals else None
|
|
if illegal_index is not None:
|
|
next_bits = get_7()
|
|
|
|
b1 = 0b11000010
|
|
b2 = 0b10000000
|
|
if next_bits is False:
|
|
b1 |= 7 << 2
|
|
next_bits = bits
|
|
else:
|
|
b1 |= (illegal_index & 0b111) << 2
|
|
|
|
first_bit = (next_bits & 0b01000000) > 0
|
|
b1 |= first_bit
|
|
b2 |= next_bits & 0b00111111
|
|
out_data.append(b1)
|
|
out_data.append(b2)
|
|
else:
|
|
out_data.append(bits)
|
|
return bytes(out_data)
|
|
|
|
|
|
def b122decode(base122_data):
|
|
decoded = []
|
|
cur_byte = 0
|
|
bit_of_byte = 0
|
|
|
|
def push7(byte):
|
|
nonlocal cur_byte, bit_of_byte
|
|
byte <<= 1
|
|
cur_byte |= (byte >> bit_of_byte)
|
|
bit_of_byte += 7
|
|
if bit_of_byte >= 8:
|
|
decoded.append(cur_byte & 0xFF)
|
|
bit_of_byte -= 8
|
|
cur_byte = (byte << (7 - bit_of_byte)) & 0xFF
|
|
|
|
for c in base122_data:
|
|
if c > 127:
|
|
illegal_index = (c >> 8) & 7
|
|
if illegal_index != 7:
|
|
push7(illegals[illegal_index])
|
|
push7(c & 127)
|
|
else:
|
|
push7(c)
|
|
return bytes(decoded)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
original_data = b"Hello World!"
|
|
encoded_data = b122encode(original_data)
|
|
print(f"Encoded data: {encoded_data}")
|
|
decoded_data = b122decode(encoded_data)
|
|
print(f"Decoded data: {decoded_data}")
|
|
|
|
original_data = 'Something else 🫨'.encode('utf-8')
|
|
encoded_data = b122encode(original_data)
|
|
print(f"Encoded data: {encoded_data.decode('utf8')}")
|
|
decoded_data = b122decode(encoded_data)
|
|
print(f"Decoded data: {decoded_data.decode('utf-8')}") |