from abc import ABCMeta, abstractmethod

from cryptography.hazmat.backends.interfaces import HashBackend

# These are actually abstractproperties on HashAlgorithm,
# but let's not worry too much about that.
class HashAlgorithm(metaclass=ABCMeta):
    @property
    def digest_size(self) -> int: ...
    @property
    def name(self) -> str: ...

class HashContext(metaclass=ABCMeta):
    @property
    def algorithm(self) -> HashAlgorithm: ...
    @abstractmethod
    def copy(self) -> HashContext: ...
    @abstractmethod
    def finalize(self) -> bytes: ...
    @abstractmethod
    def update(self, data: bytes) -> None: ...

class BLAKE2b(HashAlgorithm): ...
class BLAKE2s(HashAlgorithm): ...
class MD5(HashAlgorithm): ...
class SHA1(HashAlgorithm): ...
class SHA224(HashAlgorithm): ...
class SHA256(HashAlgorithm): ...
class SHA384(HashAlgorithm): ...
class SHA3_224(HashAlgorithm): ...
class SHA3_256(HashAlgorithm): ...
class SHA3_384(HashAlgorithm): ...
class SHA3_512(HashAlgorithm): ...
class SHA512(HashAlgorithm): ...
class SHA512_224(HashAlgorithm): ...
class SHA512_256(HashAlgorithm): ...

class SHAKE128(HashAlgorithm):
    def __init__(self, digest_size: int) -> None: ...

class SHAKE256(HashAlgorithm):
    def __init__(self, digest_size: int) -> None: ...

class Hash(HashContext):
    def __init__(self, algorithm: HashAlgorithm, backend: HashBackend | None = ...): ...
    def copy(self) -> Hash: ...
    def finalize(self) -> bytes: ...
    def update(self, data: bytes) -> None: ...
