6TF9鱈o3GwY9"w$Sqku6Èc 4ѻck2kJq*qiRB jӏmn"zdWyh!;Л{BPKP+'/פt=4o eG Fu(uLHḘb] U/]]fd$%G8j&?FvPֳm^d lm=e0[d>tv;_u6:vܡE =_P{HrF5hPP#z--ץudӭ޽ -O^| O)O[;ҋR`, WfĎ$eD$n|a! 0T[D%ԓpG~N{S19 #S)u 9uSNgӖO!Kd3zBb=9X߭s 1dARKҍ*qmR/X2@I 1_ya11V[w%]7|8,+!/KW=o#T{)d Z f6@NCfy4#cj{iuWoL;'y^Z *$(:Τ@ߖ`HЖ4,$\SmpNPo`j\ac\9.U:5:p!-pv^ܱSȆhX za)6̷#ǓC`@9ra `J{@U"w?#5~x{ߞqz#|iu~eѰ8Ǻ ׀_ʈ\ꤗ _ Y7PY Mor]uķl9utHM%}m~ߡ%b u`'Y7{%چKR#)$W@LenpnLS&d.g@#cy()t ̏'3jrߓܺ;/8 זimbo}f0TY٫5 "$Gn>XI_ >~Z^լm$,&ΓIWդn!oAۈ~tǀ EOpv|itc{`"k;S[ Uq*]@'>aO=eI}%t߅YE;<{%јn1C "KB*;  jx5⻡+Z΀JvZ.\ؔҡ{;hfՉO7 !9:QOV"#;YRE}*p%m4g2}r6qB@}6t(&7H^.͙Zܘ*< C P&4o#Z^jCp! ιUd@GYws.f܀Rw"tںqeςܻ3 PXIZ:79p8!SOq#i++D"&0K%b^F ǯw~:1øJ&oD y4WغBf72mrXoc71Λ璔 QZ;(0 Ͼ-;e5Ur`7K X&,%ݶDfπL dd4鱩lV( yUgo!)AQ UY?l-kN-iҕ {;><7&?  32IK>U[,e(9@ϴtKˋ0kVV!`H92,"{ƿVZ0puw 0Q9i׭/ybF%T.U]=a&.>j(jR/M7@pu Oȸ/@XDǙG{c0:c*p HR p/ $IS 3r")H;8:nF* 0>1]6!aO] נv@L1'6jtY?XJ|{0Sl &(hGHχ?"[Ǚujh@Th$N SV%,™d7=U3ec ֪]--vYH19(zP!rpϣ`r?d;i-YS5gFurCchhYw͞vaҦ݌"i! (``z>o\K&M:r CG#zD~yk]YI^W,J%@-:LGS^loJ_TȵflBA&;\ts] YIZЗ~' =rEuE#oD,YA7!$h)udbMCisOΊ9H]P:U~?>EGg7*;)͐TA?RdOz#+juq+_NAh@ L9Ko*Ī)wb(x08pKo7D6XM6HUH 830 2o͋v}[XFSeR#GGq 5}4\ͻ3 WjP±24?_7}U(K,TZD=4ݣ\q=dase,)`~ 'US}*|}VHk"Q{_BnuoCp<R$ͬ6ң Al ҉D~Wc#NsAczN;>5PzeS]%by 7Y= x&ws<\ Ζ 7&sCZgrj)p̅#t|,FtXRw71{⃗j\9Z䶟(}Φȏ/}T!S!LlW gZvc rUp [3nro)EHB#駠~b<Ķ&ߗzRwB2^jSd+su&*r?Ĥb~kwr8;!ɧKDUبmB-ڜ8&t֊wgFN5K]O1_۞i,d1+ԯdd@ÒkeyType )); } if ($valueType !== $this->valueType) { throw new ExpectationException(sprintf( 'Callee expected an EnumMap with value type %s, but got %s', $keyType, $this->keyType )); } if ($allowNullValues !== $this->allowNullValues) { throw new ExpectationException(sprintf( 'Callee expected an EnumMap with nullable flag %s, but got %s', ($allowNullValues ? 'true' : 'false'), ($this->allowNullValues ? 'true' : 'false') )); } } /** * Returns the number of key-value mappings in this map. */ public function size() : int { return $this->size; } /** * Returns true if this map maps one or more keys to the specified value. */ public function containsValue($value) : bool { return in_array($this->maskNull($value), $this->values, true); } /** * Returns true if this map contains a mapping for the specified key. */ public function containsKey(AbstractEnum $key) : bool { $this->checkKeyType($key); return null !== $this->values[$key->ordinal()]; } /** * Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key. * * More formally, if this map contains a mapping from a key to a value, then this method returns the value; * otherwise it returns null (there can be at most one such mapping). * * A return value of null does not necessarily indicate that the map contains no mapping for the key; it's also * possible that hte map explicitly maps the key to null. The {@see self::containsKey()} operation may be used to * distinguish these two cases. * * @return mixed */ public function get(AbstractEnum $key) { $this->checkKeyType($key); return $this->unmaskNull($this->values[$key->ordinal()]); } /** * Associates the specified value with the specified key in this map. * * If the map previously contained a mapping for this key, the old value is replaced. * * @return mixed the previous value associated with the specified key, or null if there was no mapping for the key. * (a null return can also indicate that the map previously associated null with the specified key.) * @throws IllegalArgumentException when the passed values does not match the internal value type */ public function put(AbstractEnum $key, $value) { $this->checkKeyType($key); if (! $this->isValidValue($value)) { throw new IllegalArgumentException(sprintf('Value is not of type %s', $this->valueType)); } $index = $key->ordinal(); $oldValue = $this->values[$index]; $this->values[$index] = $this->maskNull($value); if (null === $oldValue) { ++$this->size; } return $this->unmaskNull($oldValue); } /** * Removes the mapping for this key frm this map if present. * * @return mixed the previous value associated with the specified key, or null if there was no mapping for the key. * (a null return can also indicate that the map previously associated null with the specified key.) */ public function remove(AbstractEnum $key) { $this->checkKeyType($key); $index = $key->ordinal(); $oldValue = $this->values[$index]; $this->values[$index] = null; if (null !== $oldValue) { --$this->size; } return $this->unmaskNull($oldValue); } /** * Removes all mappings from this map. */ public function clear() : void { $this->values = array_fill(0, count($this->keyUniverse), null); $this->size = 0; } /** * Compares the specified map with this map for quality. * * Returns true if the two maps represent the same mappings. */ public function equals(self $other) : bool { if ($this === $other) { return true; } if ($this->size !== $other->size) { return false; } return $this->values === $other->values; } /** * Returns the values contained in this map. * * The array will contain the values in the order their corresponding keys appear in the map, which is their natural * order (the order in which the num constants are declared). */ public function values() : array { return array_values(array_map(function ($value) { return $this->unmaskNull($value); }, array_filter($this->values, function ($value) : bool { return null !== $value; }))); } public function serialize() : string { return serialize($this->__serialize()); } public function unserialize($serialized) : void { $data = unserialize($serialized); $this->__construct($data['keyType'], $data['valueType'], $data['allowNullValues']); foreach ($this->keyUniverse as $key) { if (array_key_exists($key->ordinal(), $data['values'])) { $this->put($key, $data['values'][$key->ordinal()]); } } } public function getIterator() : Traversable { foreach ($this->keyUniverse as $key) { if (null === $this->values[$key->ordinal()]) { continue; } yield $key => $this->unmaskNull($this->values[$key->ordinal()]); } } private function maskNull($value) { if (null === $value) { return NullValue::instance(); } return $value; } private function unmaskNull($value) { if ($value instanceof NullValue) { return null; } return $value; } /** * @throws IllegalArgumentException when the passed key does not match the internal key type */ private function checkKeyType(AbstractEnum $key) : void { if (get_class($key) !== $this->keyType) { throw new IllegalArgumentException(sprintf( 'Object of type %s is not the same type as %s', get_class($key), $this->keyType )); } } private function isValidValue($value) : bool { if (null === $value) { if ($this->allowNullValues) { return true; } return false; } switch ($this->valueType) { case 'mixed': return true; case 'bool': case 'boolean': return is_bool($value); case 'int': case 'integer': return is_int($value); case 'float': case 'double': return is_float($value); case 'string': return is_string($value); case 'object': return is_object($value); case 'array': return is_array($value); } return $value instanceof $this->valueType; } }