Skip to content

Instantly share code, notes, and snippets.

@JarbasAl
Created January 3, 2025 19:27
Show Gist options
  • Select an option

  • Save JarbasAl/738fa64f48ad1bc2077b060b96958449 to your computer and use it in GitHub Desktop.

Select an option

Save JarbasAl/738fa64f48ad1bc2077b060b96958449 to your computer and use it in GitHub Desktop.
base 100 with padding
from typing import Union
class B100P:
"""
B100P is a class that provides encoding and decoding methods for transforming text into an emoji-based representation
with a custom padding mechanism. The first byte of the encoded data indicates how many padding bytes were added
during encoding, which is then removed during decoding.
The padding is added to make the data length a multiple of 4, and the padding size is included as part of the encoded data.
When decoding, the padding size is read from the first byte and used to strip the padding from the decoded data.
"""
@classmethod
def encode(cls, data: Union[str, bytes], encoding: str = "utf-8") -> bytes:
"""
Encodes text into an emoji representation with padding, and prepends the padding size.
Args:
data (Union[str, bytes]): The input text to be encoded. This can either be a string (plaintext) or bytes.
encoding (str): The encoding to use if `data` is provided as a string. Default is 'utf-8'.
Returns:
bytes: The emoji-encoded byte sequence with appropriate padding and padding size indication.
Notes:
The padding is applied to ensure the length of the encoded data is a multiple of 4. The first byte in the
returned byte sequence represents the number of padding bytes added. This allows for proper decoding with
padding removal.
"""
if isinstance(data, str):
data = data.encode(encoding)
padding = (4 - len(data) % 4) % 4 # Padding to make the length a multiple of 4
data += b'\x00' * padding
# The first byte indicates how many padding bytes were added
encoded_data = [padding] + [240, 159, 0, 0] * len(data)
for i, b in enumerate(data):
encoded_data[4 * i + 3] = (b + 55) // 64 + 143
encoded_data[4 * i + 4] = (b + 55) % 64 + 128
return bytes(encoded_data)
@classmethod
def decode(cls, encoded_data: Union[str, bytes], encoding: str = "utf-8") -> bytes:
"""
Decodes an emoji representation back into text, removing padding as indicated by the first byte.
Args:
encoded_data (Union[str, bytes]): The emoji-encoded byte sequence or string to be decoded.
encoding (str): The encoding to use if `encoded_data` is provided as a string. Default is 'utf-8'.
Returns:
bytes: The decoded byte sequence of text with padding removed.
Raises:
ValueError: If the length of the input data is not divisible by 4 or contains invalid emoji encoding.
Notes:
The first byte of the encoded data indicates the padding size, and this padding is removed during decoding.
"""
if isinstance(encoded_data, str):
encoded_data = encoded_data.encode(encoding)
if len(encoded_data) == 0:
return encoded_data
# Ensure the length of data is divisible by 4 (with 1 extra byte for padding size)
if len(encoded_data) % 4 != 1:
raise ValueError('Invalid data length, should be divisible by 4 with 1 extra byte for padding indicator.')
padding = encoded_data[0] # Read the padding size from the first byte
if padding < 0 or padding > 3:
raise ValueError('Padding size must be between 0 and 3.')
# Extract the actual encoded data (excluding the padding size byte)
encoded_data = encoded_data[1:]
tmp = 0
out = [None] * (len(encoded_data) // 4)
for i, b in enumerate(encoded_data):
if i % 4 == 2:
tmp = ((b - 143) * 64) % 256
elif i % 4 == 3:
out[i // 4] = (b - 128 + tmp - 55) & 0xff
# Return decoded bytes, removing the indicated padding
decoded = bytes(out)
return decoded[:-padding] if padding else decoded # Remove the padding
import unittest
class TestB100P(unittest.TestCase):
def test_encode_empty(self):
"""Test encoding an empty byte sequence."""
self.assertEqual(B100P.encode(b''), b'\x00')
self.assertEqual(B100P.encode(''), b'\x00')
def test_decode_empty(self):
"""Test decoding an empty string."""
self.assertEqual(B100P.decode(b'\x00'), b'')
self.assertEqual(B100P.decode(''), b'')
self.assertEqual(B100P.decode(b''), b'')
def test_encode_single_byte(self):
"""Test encoding a single byte."""
self.assertEqual(b'A', B100P.decode(B100P.encode(b'A')))
self.assertEqual(b'B', B100P.decode(B100P.encode('B')))
self.assertEqual(b'_~', B100P.decode(B100P.encode(b'_~')))
self.assertEqual(b'_~', B100P.decode(B100P.encode('_~')))
def test_encode_short_string(self):
"""Test encoding a short string."""
self.assertEqual(b'hello', B100P.decode(B100P.encode(b'hello')))
def test_encode_decode_round_trip(self):
"""Test encoding and decoding round-trip."""
data = b'The quick brown fox jumps over the lazy dog.'
encoded = B100P.encode(data)
decoded = B100P.decode(encoded)
self.assertEqual(decoded, data)
def test_encode_unicode_string(self):
"""Test encoding a Unicode string."""
data = 'こんにちは' # Japanese for "hello"
encoded = B100P.encode(data)
decoded = B100P.decode(encoded)
self.assertEqual(decoded.decode('utf-8'), data)
def test_decode_invalid_character(self):
"""Test decoding with invalid Base91 characters."""
with self.assertRaises(ValueError):
B100P.decode('Invalid🎉Chars')
def test_encode_large_data(self):
"""Test encoding a large byte sequence."""
data = b'\xff' * 1000
encoded = B100P.encode(data)
decoded = B100P.decode(encoded)
self.assertEqual(decoded, data)
def test_padding_single_byte(self):
"""Test encoding and decoding with one byte that requires padding."""
data = b'\x01' # Single byte, should get padded with 3 \x00 bytes
encoded = B100P.encode(data)
self.assertEqual(encoded[0], 3) # Check padding byte
self.assertEqual(B100P.decode(encoded), data)
def test_padding_two_bytes(self):
"""Test encoding and decoding with two bytes that require padding."""
data = b'\x01\x01' # Two bytes, should get padded with 2 \x00 bytes
encoded = B100P.encode(data)
self.assertEqual(encoded[0], 2) # Check padding byte
self.assertEqual(B100P.decode(encoded), data)
def test_padding_three_bytes(self):
"""Test encoding and decoding with three bytes that require padding."""
data = b'\x01\x01\x01' # Three bytes, should get padded with 1 \x00 byte
encoded = B100P.encode(data)
self.assertEqual(encoded[0], 1) # Check padding byte
self.assertEqual(B100P.decode(encoded), data)
def test_no_padding_needed(self):
"""Test encoding and decoding with data that doesn't need padding."""
data = b'\x01\x01\x01\x01' # Exactly 4 bytes, no padding
encoded = B100P.encode(data)
self.assertEqual(encoded[0], 0) # No padding
self.assertEqual(B100P.decode(encoded), data)
def test_round_trip_padding(self):
"""Test round-trip encoding and decoding with padding."""
data = b'\x01\x01\x01' # Less than 4 bytes, needs padding
encoded = B100P.encode(data)
decoded = B100P.decode(encoded)
self.assertEqual(decoded, data) # Ensure padding is correctly removed
def test_padding_removal_after_decoding(self):
"""Test ensuring padding is correctly removed after decoding."""
data = b'\x01\x01\x01' # Less than 4 bytes, needs padding
encoded = B100P.encode(data)
self.assertEqual(encoded[0], 1) # Padding size is 1
decoded = B100P.decode(encoded)
self.assertEqual(decoded, data) # Padding should be removed
if __name__ == '__main__':
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment