92 lines
3.4 KiB
Python
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
|