rainbowadn/rainbowadn/hashing/nullability/nullablereference.py
2022-05-19 11:03:16 +03:00

92 lines
3.4 KiB
Python

from typing import Generic, Iterable, TypeVar
from rainbowadn.hashing.hash_point_format import hash_point_format
from rainbowadn.hashing.hashpoint import HashPoint
from rainbowadn.hashing.hashresolver import HashResolver
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
from rainbowadn.hashing.recursivementionable import RecursiveMentionable
from rainbowadn.hashing.resolverorigin import ResolverOrigin
__all__ = ('NullableReference', 'NullableReferenceFactory',)
ReferencedType = TypeVar('ReferencedType')
class NullableReference(RecursiveMentionable, Generic[ReferencedType]):
def __factory__(self) -> RainbowFactory['NullableReference[ReferencedType]']:
return NullableReferenceFactory(self.factory)
def points(self) -> Iterable[HashPoint]:
if isinstance(self.reference, NotNull):
return [self.reference.value]
elif isinstance(self.reference, Null):
return []
else:
raise TypeError
def __bytes__(self):
if isinstance(self.reference, NotNull):
hash_point: HashPoint[ReferencedType] = self.reference.value
assert isinstance(hash_point, HashPoint)
return hash_point.point
elif isinstance(self.reference, Null):
return HashPoint.NULL_HASH
else:
raise TypeError
def __init__(
self, reference: Nullable[HashPoint[ReferencedType]], factory: RainbowFactory[ReferencedType]
):
assert isinstance(reference, Nullable)
assert isinstance(factory, RainbowFactory)
self.reference = reference
self.factory = factory
@classmethod
def of(cls, hash_point: HashPoint[ReferencedType]) -> 'NullableReference[ReferencedType]':
assert isinstance(hash_point, HashPoint)
return cls(NotNull(hash_point), hash_point.factory)
@classmethod
def off(cls, value: ReferencedType) -> 'NullableReference[ReferencedType]':
return cls.of(HashPoint.of(value))
def str(self, tab: int) -> str:
if isinstance(self.reference, Null):
return f'-'
elif isinstance(self.reference, NotNull):
return f'{hash_point_format(self.reference.value, tab)}'
else:
raise TypeError
def __eq__(self, other):
if isinstance(other, NullableReference):
return self.reference == other.reference
else:
return NotImplemented
FReferencedType = TypeVar('FReferencedType')
class NullableReferenceFactory(RainbowFactory[NullableReference[FReferencedType]], Generic[FReferencedType]):
def __init__(self, factory: RainbowFactory[FReferencedType]):
assert isinstance(factory, RainbowFactory)
self.factory = factory
def from_bytes(self, source: bytes, resolver: HashResolver) -> NullableReference[FReferencedType]:
assert isinstance(source, bytes)
assert isinstance(resolver, HashResolver)
if source == HashPoint.NULL_HASH:
return NullableReference(Null(), self.factory)
else:
return NullableReference.of(
ResolverOrigin(self.factory, source, resolver).hash_point()
)
def loose(self) -> RainbowFactory[NullableReference[FReferencedType]]:
return self