|  |  | @ -5,7 +5,6 @@ namespace jrosset\Collections; | 
			
		
	
		
		
			
				
					
					|  |  |  | use ArrayIterator; |  |  |  | use ArrayIterator; | 
			
		
	
		
		
			
				
					
					|  |  |  | use Closure; |  |  |  | use Closure; | 
			
		
	
		
		
			
				
					
					|  |  |  | use InvalidArgumentException; |  |  |  | use InvalidArgumentException; | 
			
		
	
		
		
			
				
					
					|  |  |  | use JsonException; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | use Traversable; |  |  |  | use Traversable; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /** |  |  |  | /** | 
			
		
	
	
		
		
			
				
					|  |  | @ -27,28 +26,27 @@ class ImmutableCollection implements IImmutableCollection { | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Initialise a new collection |  |  |  |      * Initialise a new collection | 
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param array|Traversable|null $other The initial values |  |  |  |      * @param iterable|null                                            $other The initial values | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @psalm-param array<TKey, TValue>|Traversable<TKey, TValue>|null |  |  |  |      * @psalm-param array<TKey, TValue>|Traversable<TKey, TValue>|null $other | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @throws InvalidArgumentException If the initial values aren't valid |  |  |  |      * @throws InvalidArgumentException If the initial values aren't valid | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function __construct ($other = null) { |  |  |  |     public function __construct (?iterable $other = null) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         $this->_initialize($other); |  |  |  |         $this->_initialize($other); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Initialise the internals elements |  |  |  |      * Initialise the internals elements | 
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param array|Traversable|null $other The initial values |  |  |  |      * @param iterable|null                                            $other The initial values | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @psalm-param array<TKey, TValue>|Traversable<TKey, TValue>|null |  |  |  |      * @psalm-param array<TKey, TValue>|Traversable<TKey, TValue>|null $other | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @throws InvalidArgumentException If the initial values aren't valid |  |  |  |      * @throws InvalidArgumentException If the initial values aren't valid | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @internal |  |  |  |      * @internal | 
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     protected function _initialize ($other = null) { |  |  |  |     protected function _initialize (?iterable $other = null) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         $this->elements = []; |  |  |  |         $this->elements = []; | 
			
		
	
		
		
			
				
					
					|  |  |  |         if ($other !== null) { |  |  |  |         if ($other !== null) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             if (!is_array($other) && !$other instanceof Traversable) { |  |  |  |             if (!is_array($other) && !$other instanceof Traversable) { | 
			
		
	
	
		
		
			
				
					|  |  | @ -73,7 +71,7 @@ class ImmutableCollection implements IImmutableCollection { | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @internal |  |  |  |      * @internal | 
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     protected function _set ($key, $value): self { |  |  |  |     protected function _set (int|string $key, mixed $value): self { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         $this->elements[$this->_normalizeKey($key)] = $value; |  |  |  |         $this->elements[$this->_normalizeKey($key)] = $value; | 
			
		
	
		
		
			
				
					
					|  |  |  |         return $this; |  |  |  |         return $this; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
	
		
		
			
				
					|  |  | @ -103,7 +101,7 @@ class ImmutableCollection implements IImmutableCollection { | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @internal |  |  |  |      * @internal | 
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     protected function _add (...$values): self { |  |  |  |     protected function _add (mixed ...$values): self { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         foreach ($values as $value) { |  |  |  |         foreach ($values as $value) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             $this->elements[] = $value; |  |  |  |             $this->elements[] = $value; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
	
		
		
			
				
					|  |  | @ -134,53 +132,49 @@ class ImmutableCollection implements IImmutableCollection { | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @return array-key The normalized key |  |  |  |      * @return array-key The normalized key | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @psalm-return TKey |  |  |  |      * @psalm-return TKey | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     protected function _normalizeKey ($key) { |  |  |  |     protected function _normalizeKey (int|string $key): int|string { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         return $key; |  |  |  |         return $key; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @inheritDoc |  |  |  |      * @inheritDoc | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function getIterator () { |  |  |  |     public function getIterator (): ArrayIterator { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         return new ArrayIterator($this->elements); |  |  |  |         return new ArrayIterator($this->elements); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @inheritDoc |  |  |  |      * @inheritDoc | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function offsetExists ($offset): bool { |  |  |  |     public function offsetExists (mixed $offset): bool { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         return $this->exists($offset); |  |  |  |         return $this->exists($offset); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @inheritDoc |  |  |  |      * @inheritDoc | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function offsetGet ($offset) { |  |  |  |     public function offsetGet (mixed $offset): mixed { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         return $this->get($offset); |  |  |  |         return $this->get($offset); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @inheritDoc |  |  |  |      * @inheritDoc | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function offsetSet ($offset, $value): void { |  |  |  |     public function offsetSet (mixed $offset, mixed $value): void { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         throw new ImmutableException(); |  |  |  |         throw new ImmutableException(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @inheritDoc |  |  |  |      * @inheritDoc | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function offsetUnset ($offset): void { |  |  |  |     public function offsetUnset (mixed $offset): void { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         throw new ImmutableException(); |  |  |  |         throw new ImmutableException(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     public function __serialize (): array { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * @inheritDoc |  |  |  |         return [ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |             'elements' => $this->elements, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     public function serialize (): ?string { |  |  |  |         ]; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         return serialize($this->elements); |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     public function __unserialize (array $data): void { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * @inheritDoc |  |  |  |         $this->_initialize($data['elements']); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function unserialize ($data) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         $this->_initialize(unserialize($data)); |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
	
		
		
			
				
					|  |  | @ -206,26 +200,26 @@ class ImmutableCollection implements IImmutableCollection { | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @inheritDoc |  |  |  |      * @inheritDoc | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function exists ($key): bool { |  |  |  |     public function exists (int|string $key): bool { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         return isset($this->elements[$this->_normalizeKey($key)]); |  |  |  |         return isset($this->elements[$this->_normalizeKey($key)]); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @inheritDoc |  |  |  |      * @inheritDoc | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function contains ($value, bool $strict = false): bool { |  |  |  |     public function contains (mixed $value, bool $strict = false): bool { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         return in_array($value, $this->elements, $strict); |  |  |  |         return in_array($value, $this->elements, $strict); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @inheritDoc |  |  |  |      * @inheritDoc | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function get ($key) { |  |  |  |     public function get (int|string $key): mixed { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         return $this->elements[$this->_normalizeKey($key)] ?? null; |  |  |  |         return $this->elements[$this->_normalizeKey($key)] ?? null; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @inheritDoc |  |  |  |      * @inheritDoc | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function key ($value, bool $strict = false) { |  |  |  |     public function key (mixed $value, bool $strict = false): int|string|null { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         foreach ($this->elements as $currentKey => $currentValue) { |  |  |  |         foreach ($this->elements as $currentKey => $currentValue) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             if (($strict && $value === $currentValue) || (!$strict && $value == $currentValue)) { |  |  |  |             if (($strict && $value === $currentValue) || (!$strict && $value == $currentValue)) { | 
			
		
	
		
		
			
				
					
					|  |  |  |                 return $currentKey; |  |  |  |                 return $currentKey; | 
			
		
	
	
		
		
			
				
					|  |  | @ -309,11 +303,9 @@ class ImmutableCollection implements IImmutableCollection { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @inheritDoc |  |  |  |      * @inheritDoc | 
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @throws JsonException |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function jsonSerialize () { |  |  |  |     public function jsonSerialize (): mixed { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         return json_encode($this->elements, JSON_THROW_ON_ERROR); |  |  |  |         return $this->elements; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
	
		
		
			
				
					|  |  | 
 |