From de059122d16d8f348242ec4df74a5adc1a86de31 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Sat, 17 Feb 2024 17:13:01 +0700 Subject: [PATCH] feat: LazyList, not yet used. (#11) --- src/ListInterface.php | 24 ++++++ src/Transformer/Model/LazyList.php | 115 +++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 src/ListInterface.php create mode 100644 src/Transformer/Model/LazyList.php diff --git a/src/ListInterface.php b/src/ListInterface.php new file mode 100644 index 00000000..7086f9a7 --- /dev/null +++ b/src/ListInterface.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\Mapper; + +/** + * @template TKey of int + * @template TValue + * @extends \IteratorAggregate + * @extends \ArrayAccess + */ +interface ListInterface extends \ArrayAccess, \IteratorAggregate, \Countable +{ +} diff --git a/src/Transformer/Model/LazyList.php b/src/Transformer/Model/LazyList.php new file mode 100644 index 00000000..19b6b98d --- /dev/null +++ b/src/Transformer/Model/LazyList.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\Mapper\Transformer\Model; + +use Rekalogika\Mapper\Context\Context; +use Rekalogika\Mapper\ListInterface; +use Rekalogika\Mapper\MainTransformer\MainTransformerInterface; +use Rekalogika\Mapper\Transformer\ArrayLikeMetadata\ArrayLikeMetadata; +use Rekalogika\Mapper\Transformer\MainTransformerAwareTrait; +use Rekalogika\Mapper\Transformer\Trait\ArrayLikeTransformerTrait; + +/** + * Discards source key, and use incremental integer key in the target. + * + * @template TValue + * @implements ListInterface + * @internal + */ +final class LazyList implements ListInterface +{ + use MainTransformerAwareTrait; + use ArrayLikeTransformerTrait; + + /** + * @var array + */ + private array $cachedData = []; + private bool $isCached = false; + + /** + * @param (\Traversable&\ArrayAccess&\Countable)|array $source + */ + public function __construct( + private (\Traversable&\ArrayAccess&\Countable)|array $source, + MainTransformerInterface $mainTransformer, + private ArrayLikeMetadata $metadata, + private Context $context, + ) { + $this->mainTransformer = $mainTransformer; + } + + public function offsetExists(mixed $offset): bool + { + return isset($this->cachedData[$offset]) || isset($this->source[$offset]); + } + + public function offsetGet(mixed $offset): mixed + { + if (!$this->isCached) { + foreach($this->getIterator() as $i); + } + + return $this->cachedData[$offset]; + } + + public function offsetSet(mixed $offset, mixed $value): void + { + throw new \BadMethodCallException('LazyArray is immutable.'); + } + + public function offsetUnset(mixed $offset): void + { + throw new \BadMethodCallException('LazyArray is immutable.'); + } + + public function getIterator(): \Traversable + { + if ($this->isCached) { + yield from $this->cachedData; + + return; + } + + $i = 0; + + /** + * @var mixed $sourceMemberValue + */ + foreach ($this->source as $sourceMemberKey => $sourceMemberValue) { + /** + * @var TValue $value + */ + [, $value] = $this->transformMember( + sourceMemberKey: $sourceMemberKey, + sourceMemberValue: $sourceMemberValue, + metadata: $this->metadata, + context: $this->context, + ); + + $this->cachedData[$i] = $value; + + yield $value; + + $i++; + } + + $this->isCached = true; + } + + public function count(): int + { + return count($this->source); + } +}