Skip to content

Commit

Permalink
AccessTrait added and used in ArrayView.
Browse files Browse the repository at this point in the history
  • Loading branch information
Smoren committed Mar 11, 2024
1 parent 9df60a6 commit 0fb430b
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 95 deletions.
4 changes: 4 additions & 0 deletions src/Interfaces/ArrayViewInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,14 @@ public function count(): int;

/**
* @param numeric|string|ArraySelectorInterface $offset
*
* @return bool
*/
public function offsetExists($offset): bool;

/**
* @param numeric|string|ArraySelectorInterface $offset
*
* @return T|array<T>
*/
#[\ReturnTypeWillChange]
Expand All @@ -99,12 +101,14 @@ public function offsetGet($offset);
/**
* @param numeric|string|ArraySelectorInterface $offset
* @param T|array<T>|ArrayViewInterface<T> $value
*
* @return void
*/
public function offsetSet($offset, $value): void;

/**
* @param numeric|string|ArraySelectorInterface $offset
*
* @return void
*/
public function offsetUnset($offset): void;
Expand Down
126 changes: 126 additions & 0 deletions src/Traits/ArrayViewAccessTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?php

namespace Smoren\ArrayView\Traits;

use Smoren\ArrayView\Exceptions\IndexError;
use Smoren\ArrayView\Exceptions\KeyError;
use Smoren\ArrayView\Exceptions\NotSupportedError;
use Smoren\ArrayView\Exceptions\ReadonlyError;
use Smoren\ArrayView\Interfaces\ArraySelectorInterface;
use Smoren\ArrayView\Interfaces\ArrayViewInterface;
use Smoren\ArrayView\Selectors\SliceSelector;
use Smoren\ArrayView\Structs\Slice;

/**
* @template T
*/
trait ArrayViewAccessTrait
{
/**
* @param numeric|string|ArraySelectorInterface $offset
*
* @return bool
*
* {@inheritDoc}
*/
public function offsetExists($offset): bool
{
if (\is_numeric($offset)) {
return $this->numericOffsetExists($offset);
}

if (\is_string($offset) && Slice::isSlice($offset)) {
return true;
}

if ($offset instanceof ArraySelectorInterface) {
return true;
}

return false;
}

/**
* @param numeric|string|ArraySelectorInterface $offset
*
* @return T|array<T>
*
* {@inheritDoc}
*/
#[\ReturnTypeWillChange]
public function offsetGet($offset)
{
/** @var mixed $offset */
if (\is_numeric($offset)) {
if (!$this->numericOffsetExists($offset)) {
throw new IndexError("Index {$offset} is out of range.");
}
return $this->source[$this->convertIndex(\intval($offset))];
}

if (\is_string($offset) && Slice::isSlice($offset)) {
return $this->subview(new SliceSelector($offset))->toArray();
}

if ($offset instanceof ArraySelectorInterface) {
return $this->subview($offset)->toArray();
}

$strOffset = \is_scalar($offset) ? \strval($offset) : \gettype($offset);
throw new KeyError("Invalid key: \"{$strOffset}\".");
}

/**
* @param numeric|string|ArraySelectorInterface $offset
* @param T|array<T>|ArrayViewInterface<T> $value
*
* @return void
*
* {@inheritDoc}
*/
public function offsetSet($offset, $value): void
{
/** @var mixed $offset */
if ($this->isReadonly()) {
throw new ReadonlyError("Cannot modify a readonly view.");
}

if (\is_numeric($offset)) {
if (!$this->numericOffsetExists($offset)) {
throw new IndexError("Index {$offset} is out of range.");
}

// @phpstan-ignore-next-line
$this->source[$this->convertIndex(\intval($offset))] = $value;
return;
}

if (\is_string($offset) && Slice::isSlice($offset)) {
/** @var array<T>|ArrayViewInterface<T> $value */
$this->subview(new SliceSelector($offset))->set($value);
return;
}

if ($offset instanceof ArraySelectorInterface) {
$this->subview($offset)->set($value);
return;
}

$strOffset = \is_scalar($offset) ? \strval($offset) : \gettype($offset);
throw new KeyError("Invalid key: \"{$strOffset}\".");
}

/**
* @param numeric|string|ArraySelectorInterface $offset
*
* @return void
*
* @throws NotSupportedError
*
* {@inheritDoc}
*/
public function offsetUnset($offset): void
{
throw new NotSupportedError();
}
}
101 changes: 6 additions & 95 deletions src/Views/ArrayView.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@
namespace Smoren\ArrayView\Views;

use Smoren\ArrayView\Exceptions\IndexError;
use Smoren\ArrayView\Exceptions\KeyError;
use Smoren\ArrayView\Exceptions\SizeError;
use Smoren\ArrayView\Exceptions\NotSupportedError;
use Smoren\ArrayView\Exceptions\ReadonlyError;
use Smoren\ArrayView\Exceptions\ValueError;
use Smoren\ArrayView\Interfaces\ArraySelectorInterface;
use Smoren\ArrayView\Interfaces\ArrayViewInterface;
use Smoren\ArrayView\Interfaces\MaskSelectorInterface;
use Smoren\ArrayView\Selectors\MaskSelector;
use Smoren\ArrayView\Selectors\SliceSelector;
use Smoren\ArrayView\Structs\Slice;
use Smoren\ArrayView\Traits\ArrayViewAccessTrait;
use Smoren\ArrayView\Util;

/**
Expand All @@ -25,6 +22,11 @@
*/
class ArrayView implements ArrayViewInterface
{
/**
* @use ArrayViewAccessTrait<T>
*/
use ArrayViewAccessTrait;

/**
* @var array<T>|ArrayViewInterface<T>
*/
Expand Down Expand Up @@ -215,97 +217,6 @@ public function isReadonly(): bool
return $this->readonly;
}

/**
* {@inheritDoc}
*/
public function offsetExists($offset): bool
{
if (\is_numeric($offset)) {
return $this->numericOffsetExists($offset);
}

if (\is_string($offset) && Slice::isSlice($offset)) {
return true;
}

if ($offset instanceof ArraySelectorInterface) {
return true;
}

return false;
}

/**
* {@inheritDoc}
*/
#[\ReturnTypeWillChange]
public function offsetGet($offset)
{
/** @var mixed $offset */
if (\is_numeric($offset)) {
if (!$this->numericOffsetExists($offset)) {
throw new IndexError("Index {$offset} is out of range.");
}
return $this->source[$this->convertIndex(\intval($offset))];
}

if (\is_string($offset) && Slice::isSlice($offset)) {
return $this->subview(new SliceSelector($offset))->toArray();
}

if ($offset instanceof ArraySelectorInterface) {
return $this->subview($offset)->toArray();
}

$strOffset = \is_scalar($offset) ? \strval($offset) : \gettype($offset);
throw new KeyError("Invalid key: \"{$strOffset}\".");
}

/**
* {@inheritDoc}
*/
public function offsetSet($offset, $value): void
{
/** @var mixed $offset */
if ($this->isReadonly()) {
throw new ReadonlyError("Cannot modify a readonly view.");
}

if (\is_numeric($offset)) {
if (!$this->numericOffsetExists($offset)) {
throw new IndexError("Index {$offset} is out of range.");
}

// @phpstan-ignore-next-line
$this->source[$this->convertIndex(\intval($offset))] = $value;
return;
}

if (\is_string($offset) && Slice::isSlice($offset)) {
/** @var array<T>|ArrayViewInterface<T> $value */
$this->subview(new SliceSelector($offset))->set($value);
return;
}

if ($offset instanceof ArraySelectorInterface) {
$this->subview($offset)->set($value);
return;
}

$strOffset = \is_scalar($offset) ? \strval($offset) : \gettype($offset);
throw new KeyError("Invalid key: \"{$strOffset}\".");
}

/**
* @throws NotSupportedError
*
* {@inheritDoc}
*/
public function offsetUnset($offset): void
{
throw new NotSupportedError();
}

/**
* {@inheritDoc}
*/
Expand Down

0 comments on commit 0fb430b

Please sign in to comment.