decode WIP

This commit is contained in:
2026-07-07 23:12:39 +03:00
parent 257db7a6a2
commit 65064d295d
+139 -1
View File
@@ -45,6 +45,22 @@ def int_to_char(value: int) -> str:
raise ValueError("Value must be in the range [0, 63] for base64 encoding.")
def char_to_int(char: str) -> int:
"""Convert a base64 character to its corresponding integer value."""
if "0" <= char <= "9":
return ord(char) - ord("0")
elif "a" <= char <= "z":
return ord(char) - ord("a") + 10
elif "A" <= char <= "Z":
return ord(char) - ord("A") + 36
elif char == "+":
return 62
elif char == "/":
return 63
else:
raise ValueError("Character must be a valid base64 character.")
def encode_golomb_Mshift(cnt: int, bpp: int) -> int:
"""Calculate Mshift paramter for encoding."""
Mshift = bpp - (cnt.bit_length() - 1) - 1
@@ -122,10 +138,117 @@ def encode_set(hash_values: List[int], bpp: int) -> str:
return int_to_char(bpp) + int_to_char(Mshift) + base64_chars
def rpmsetcmp():
def decode_base64(encoded_str: str) -> List[int]:
"""Decode a base64 string into a list of bits."""
bits = []
for char in encoded_str:
value = char_to_int(char)
for i in range(6):
bits.append((value >> (5 - i)) & 1)
return bits
def decode_golomb(bits: List[int], Mshift: int) -> List[int]:
"""Decode a list of bits encoded with Golomb coding into delta values."""
delta_values = []
i = 0
while i < len(bits):
q = 0
while i < len(bits) and bits[i] == 0:
q += 1
i += 1
if i >= len(bits):
if q > 5:
raise ValueError("Invalid Golomb encoding: too many leading zeros.")
break
i += 1 # skip the separator bit
r = 0
for j in range(Mshift):
if i < len(bits):
if bits[i] == 1:
r |= 1 << j
else:
i += 1
delta_value = (q << Mshift) | r
delta_values.append(delta_value)
return delta_values
def decode_delta(delta_values: List[int]) -> List[int]:
"""Decode a list of delta values into hash values."""
last_hash = delta_values[0]
hash_values = [last_hash]
for i in range(1, len(delta_values)):
hash_values.append(hash_values[i - 1] + delta_values[i])
return hash_values
def downsample_set(hash_values: List[int], bpp: int) -> List[int]:
"""Reduce a set of (bpp + 1) values to a set of bpp values, keeping it sorted."""
# WIP
pass
def decode_set_init(encoded_str: str) -> Tuple[int, int]:
"""Decode the initial part of the set-string to extract bpp and Mshift."""
if len(encoded_str) < 2:
raise ValueError("Encoded string is too short to contain bpp and Mshift.")
bpp = char_to_int(encoded_str[0])
Mshift = char_to_int(encoded_str[1])
assert check_bpp(bpp), "bpp must be between 2 and 64"
assert check_Mshift(Mshift), "Mshift must be between 1 and 63"
return bpp, Mshift
def decode_set(encoded_str: str, Mshift: int) -> List[int]:
"""Decode the set-string representation into a list of hash values."""
data_str = encoded_str[2:]
str_bits = decode_base64(data_str)
str_delta = decode_golomb(str_bits, Mshift)
hash_values = decode_delta(str_delta)
return hash_values
def rpmsetcmp(str1: str, str2: str) -> int:
if str1[:3] == "set:":
str1 = str1[3:]
if str2[:3] == "set:":
str2 = str2[3:]
bpp1, Mshift1 = decode_set_init(str1)
bpp2, Mshift2 = decode_set_init(str2)
hash_values1 = decode_set(str1, Mshift1)
hash_values2 = decode_set(str2, Mshift2)
while bpp1 > bpp2:
hash_values1 = downsample_set(hash_values1, bpp1)
bpp1 -= 1
while bpp2 > bpp1:
hash_values2 = downsample_set(hash_values2, bpp2)
bpp2 -= 1
# WIP
return 0
def set_new() -> Set:
"""Create a new Set instance with cnt initialized to 0 and an empty list of labels."""
return Set(cnt=0, labels=[])
@@ -190,3 +313,18 @@ if __name__ == "__main__":
result = set_fini(my_set, 8)
print(result)
set_free(my_set)
# example with comparison
set1 = set_new()
set_add(set1, "label1")
set_add(set1, "label2")
str1 = set_fini(set1, 8)
set2 = set_new()
set_add(set2, "label1")
set_add(set2, "label2")
set_add(set2, "label3")
str2 = set_fini(set2, 8)
assert str1 is not None and str2 is not None, "Set strings should not be None"
comparison_result = rpmsetcmp(str1, str2)
assert comparison_result == -1, "Expected str1 to be less than str2"
print(comparison_result)