diff --git a/main.py b/main.py index 0f0b17d..0d107b0 100644 --- a/main.py +++ b/main.py @@ -158,6 +158,7 @@ def main(): tree = tree.create(target) print(tree.reference.str(0)) tree = tree.add(HashPoint.of(Plain(b'NEWKEY'))) + tree = tree.remove(HashPoint.of(Plain(b'Q'))) print(tree.reference.str(0)) target = tree.reference eeed = Encrypted.encrypt(target, key) diff --git a/rainbowadn/chain/composition/__init__.py b/rainbowadn/chain/composition/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/rainbowadn/data/collection/pair.py b/rainbowadn/data/collection/pair.py new file mode 100644 index 0000000..3b89700 --- /dev/null +++ b/rainbowadn/data/collection/pair.py @@ -0,0 +1,62 @@ +from typing import Generic, Iterable, TypeVar + +from rainbowadn.hashing.hash_point_format import hash_point_format, tabulate +from rainbowadn.hashing.hashpoint import HashPoint +from rainbowadn.hashing.hashresolver import HashResolver +from rainbowadn.hashing.rainbow_factory import RainbowFactory +from rainbowadn.hashing.recursivementionable import RecursiveMentionable +from rainbowadn.hashing.resolverorigin import ResolverOrigin + +__all__ = ('Pair', 'PairFactory',) + +E0Type = TypeVar('E0Type') +E1Type = TypeVar('E1Type') + + +class Pair( + RecursiveMentionable, + Generic[E0Type, E1Type] +): + def __init__(self, element0: HashPoint[E0Type], element1: HashPoint[E1Type]): + assert isinstance(element0, HashPoint) + assert isinstance(element1, HashPoint) + self.element0 = element0 + self.element1 = element1 + + def points(self) -> Iterable[HashPoint]: + return [self.element0, self.element1] + + def __bytes__(self): + return bytes(self.element0) + bytes(self.element1) + + def __factory__(self) -> RainbowFactory['Pair[E0Type, E1Type]']: + return PairFactory(self.element0.factory, self.element1.factory) + + def str(self, tab: int) -> str: + assert isinstance(tab, int) + return f'(pair)' \ + f'{tabulate(tab)}{hash_point_format(self.element0, tab)}' \ + f'{tabulate(tab)}{hash_point_format(self.element1, tab)}' + + +class PairFactory( + RainbowFactory[Pair[E0Type, E1Type]], + Generic[E0Type, E1Type] +): + def __init__( + self, + e0_factory: RainbowFactory[E0Type], + e1_factory: RainbowFactory[E1Type], + ): + assert isinstance(e0_factory, RainbowFactory) + assert isinstance(e1_factory, RainbowFactory) + self.e0_factory = e0_factory + self.e1_factory = e1_factory + + def from_bytes(self, source: bytes, resolver: HashResolver) -> Pair[E0Type, E1Type]: + assert isinstance(source, bytes) + assert isinstance(resolver, HashResolver) + return Pair( + ResolverOrigin(self.e0_factory, source[:HashPoint.HASH_LENGTH], resolver).hash_point(), + ResolverOrigin(self.e1_factory, source[HashPoint.HASH_LENGTH:], resolver).hash_point(), + ) diff --git a/rainbowadn/data/collection/trees/binary/activebinarytree.py b/rainbowadn/data/collection/trees/binary/activebinarytree.py index 48b9221..7645cfd 100644 --- a/rainbowadn/data/collection/trees/binary/activebinarytree.py +++ b/rainbowadn/data/collection/trees/binary/activebinarytree.py @@ -9,7 +9,7 @@ from rainbowadn.data.collection.trees.binary.binarytree import BinaryTree, Binar from rainbowadn.data.collection.trees.binary.binarytreebalancingprotocol import BinaryTreeBalancingProtocol from rainbowadn.data.collection.trees.binary.binarytreecreationprotocol import BinaryTreeCreationProtocol from rainbowadn.data.collection.trees.binary.querybinarytree import QueryBinaryTree -from rainbowadn.data.collection.trees.comparison.comparator import (Comparator, Comparison, Left, Replace, Right) +from rainbowadn.data.collection.trees.comparison.comparator import (Comparator, Comparison, Equal, Left, Replace, Right) from rainbowadn.data.collection.trees.comparison.keyedcomparator import KeyedComparator from rainbowadn.hashing.hashpoint import HashPoint from rainbowadn.hashing.nullability.notnull import NotNull @@ -90,6 +90,48 @@ class ActiveBinaryTree( else: return self.creation.tree(self, self, key) + def pop(self) -> tuple['ActiveBinaryTree[ActiveKeyType, MetaDataType]', HashPoint[ActiveKeyType]]: + assert self.creation.splittable(self) + treel: ActiveBinaryTree[ActiveKeyType, MetaDataType] + original: HashPoint[ActiveKeyType] + treer: ActiveBinaryTree[ActiveKeyType, MetaDataType] + treel, original, _, treer = self.creation.split(self) + assert isinstance(treel, ActiveBinaryTree) + assert isinstance(original, HashPoint) + assert isinstance(treer, ActiveBinaryTree) + if not self.creation.splittable(treel): + return treer, original + elif not self.creation.splittable(treer): + return treel, original + else: + treel, key = treel.pop() + assert isinstance(treel, ActiveBinaryTree) + assert isinstance(key, HashPoint) + return self.creation.tree(treel, treer, key), original + + def remove(self, key: HashPoint[ActiveKeyType]) -> 'ActiveBinaryTree[ActiveKeyType, MetaDataType]': + assert isinstance(key, HashPoint) + if self.creation.splittable(self): + treel: ActiveBinaryTree[ActiveKeyType, MetaDataType] + original: HashPoint[ActiveKeyType] + treer: ActiveBinaryTree[ActiveKeyType, MetaDataType] + treel, original, _, treer = self.creation.split(self) + assert isinstance(treel, ActiveBinaryTree) + assert isinstance(original, HashPoint) + assert isinstance(treer, ActiveBinaryTree) + comparison: Comparison = self.comparator.compare(original, key) + assert isinstance(comparison, Comparison) + if isinstance(comparison, Equal): + return self.pop()[0] + elif isinstance(comparison, Left): + return self.creation.tree(treel.remove(key), treer, original) + elif isinstance(comparison, Right): + return self.creation.tree(treel, treer.remove(key), original) + else: + raise TypeError + else: + return self + def query_tree(self) -> QueryCollectionInterface[ActiveKeyType]: return KeyMetadataQueryCollection( self.protocol.empty_metadata(), diff --git a/rainbowadn/encryption/encrypted.py b/rainbowadn/encryption/encrypted.py index 6a2f202..8f3f33a 100644 --- a/rainbowadn/encryption/encrypted.py +++ b/rainbowadn/encryption/encrypted.py @@ -116,18 +116,19 @@ class EncryptedFactory(RainbowFactory[Encrypted[EncryptedType]], Generic[Encrypt ) hashpoints = tuple(decrypted.points()) if isinstance(decrypted, RecursiveMentionable) else () assert len(hashpoints) == resolution_size + resolution: tuple[HashPoint[Encrypted], ...] = tuple( + ResolverOrigin( + EncryptedFactory( + hashpoint.factory, + self.key + ), + plain[8 + i * HashPoint.HASH_LENGTH: 8 + (i + 1) * HashPoint.HASH_LENGTH], + resolver + ).hash_point() for i, hashpoint in enumerate(hashpoints) + ) encrypted.__init__( self.key, - tuple( - ResolverOrigin( - EncryptedFactory( - hashpoint.factory, - self.key - ), - plain[8 + i * HashPoint.HASH_LENGTH: 8 + (i + 1) * HashPoint.HASH_LENGTH], - resolver - ).hash_point() for i, hashpoint in enumerate(hashpoints) - ), + resolution, decrypted ) return encrypted