59 lines
1.9 KiB
Python
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
|