rainbowadn/rainbowadn/hashing/hashpoint.py
2022-05-08 21:56:17 +03:00

59 lines
1.9 KiB
Python

import hashlib
from typing import Generic, TypeVar
from rainbowadn.hashing.hashmentionable import HashMentionable
from rainbowadn.hashing.nullability.notnull import NotNull
from rainbowadn.hashing.nullability.null import Null
from rainbowadn.hashing.nullability.nullable import Nullable
from rainbowadn.hashing.rainbow_factory import RainbowFactory
__all__ = ('HashPoint',)
HashMentioned = TypeVar('HashMentioned')
class HashPoint(Generic[HashMentioned]):
def __init__(self, factory: RainbowFactory[HashMentioned], point: bytes, value: Nullable[HashMentioned]):
assert isinstance(factory, RainbowFactory)
assert isinstance(point, bytes)
assert isinstance(value, Nullable)
assert len(point) == self.HASH_LENGTH
self.factory = factory
self.point = point
self.value = value
def __bytes__(self):
return self.point
HASH_LENGTH = 32
NULL_HASH = b'\0' * HASH_LENGTH
@classmethod
def hash(cls, source: bytes) -> bytes:
assert isinstance(source, bytes)
return hashlib.sha256(source).digest()
@classmethod
def bytes_of_mentioned(cls, mentioned: HashMentionable):
assert isinstance(mentioned, HashMentionable)
topology_hash: bytes = mentioned.__topology_hash__()
assert isinstance(topology_hash, bytes)
assert len(topology_hash) == cls.HASH_LENGTH
return topology_hash + bytes(mentioned)
@classmethod
def of(cls, mentioned: HashMentioned) -> 'HashPoint[HashMentioned]':
assert isinstance(mentioned, HashMentionable)
return cls(
mentioned.__factory__(), cls.hash(cls.bytes_of_mentioned(mentioned)), NotNull(mentioned)
)
def loose(self) -> 'HashPoint[HashMentioned]':
return HashPoint(self.factory, self.point, Null())
def __eq__(self, other):
if isinstance(other, HashPoint):
return self.point == other.point
else:
return NotImplemented