Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 40 additions & 4 deletions hashes/adler32.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,56 @@
MOD_ADLER = 65521


def adler32(plain_text: str) -> int:
def adler32(plain_text: str | bytes) -> int:
"""
Function implements adler-32 hash.
Iterates and evaluates a new value for each character
Iterates and evaluates a new value for each byte in the data.
If a string is passed, it is encoded to UTF-8 bytes per the Adler-32 specification.

>>> adler32('Algorithms')
363791387

>>> adler32('go adler em all')
708642122

>>> adler32('€100')
196018850

>>> adler32(b'Algorithms')
363791387

>>> adler32(b'')
1

>>> adler32('')
1

>>> import zlib
>>> adler32('日本語テスト') == zlib.adler32('日本語テスト'.encode())
True

>>> adler32(b'\\x00\\xff\\xfe') == zlib.adler32(b'\\x00\\xff\\xfe')
True

>>> adler32(123)
Traceback (most recent call last):
...
TypeError: plain_text must be str or bytes-like, not int
"""
if not isinstance(plain_text, (str, bytes, bytearray)):
msg = f"plain_text must be str or bytes-like, not {type(plain_text).__name__}"
raise TypeError(msg)

data = plain_text.encode("utf-8") if isinstance(plain_text, str) else plain_text
a = 1
b = 0
for plain_chr in plain_text:
a = (a + ord(plain_chr)) % MOD_ADLER
for byte in data:
a = (a + byte) % MOD_ADLER
b = (b + a) % MOD_ADLER
return (b << 16) | a


if __name__ == "__main__":
import doctest

doctest.testmod()
Loading