Overview

Namespaces

  • esperecyan
    • webidl
      • lib

Classes

  • BooleanType
  • DictionaryType
  • FloatType
  • IntegerType
  • NullableType
  • ObjectType
  • SequenceType
  • StringType
  • Type
  • UnionType

Traits

  • Error
  • Overview
  • Namespace
  • Class
  • Tree
  1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46:  47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66:  67:  68:  69:  70:  71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82:  83:  84:  85:  86:  87:  88:  89:  90:  91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 
<?php
namespace esperecyan\webidl\lib;

use esperecyan\webidl\Record;

/** @internal */
class DictionaryType
{
    use Utility;
    
    /**
     * 与えられた値を文字列キーでアクセス可能な値に変換する。
     * @param mixed $value
     * @return array|\ArrayAccess
     */
    private static function convertToArrayAccess($value)
    {
        if ($value instanceof \ArrayAccess) {
            $array = $value;
        } elseif ($value instanceof \Traversable) {
            $array = SequenceType::convertToRewindable($value);
            if ($array instanceof \Traversable) {
                set_error_handler(function ($severity, $message) {
                    return $severity === E_WARNING
                        ? $message === 'Illegal offset type'
                        : preg_match('/^Resource ID#([0-9]+) used as offset, casting to integer \\(\\1\\)$/', $message);
                }, E_WARNING | (PHP_MAJOR_VERSION === 5 ? E_STRICT : E_NOTICE));
                $array = iterator_to_array($array);
                restore_error_handler();
            }
        } else {
            $array = (array)$value;
        }
        
        return $array;
    }
    
    /**
     * 与えられた値を、指定された dictionary 型に変換して返します。
     * @link https://www.w3.org/TR/WebIDL-1/#idl-dictionary WebIDL Level 1
     * @link https://www.w3.org/TR/WebIDL-1/#idl-dictionaries WebIDL Level 1
     * @param mixed $value
     * @param string $identifier
     * @param array $pseudoTypes
     * @throws \DomainException dictionary メンバと同じキーを持つ $value の要素について、型が合致しない場合。
     * @return array
     */
    public static function toDictionary($value, $identifier, $pseudoTypes)
    {
        $array = self::convertToArrayAccess($value);
        
        $dictionary = [];
        
        foreach ($pseudoTypes[$identifier] as $dictionaryMemberIdentifier => $dictionaryMemberInfo) {
            if (isset($array[$dictionaryMemberIdentifier])) {
                $dictionaryMember = $array[$dictionaryMemberIdentifier];
                try {
                    $dictionary[$dictionaryMemberIdentifier]
                        = Type::to($dictionaryMemberInfo['type'], $dictionaryMember, $pseudoTypes);
                } catch (\LogicException $exception) {
                    if ($exception instanceof \InvalidArgumentException || $exception instanceof \DomainException) {
                        throw new \DomainException(sprintf(
                            'In "%s" member of %s, expected %s',
                            $dictionaryMemberIdentifier,
                            $identifier,
                            $dictionaryMemberInfo['type']
                        ), 0, $exception);
                    } else {
                        throw $exception;
                    }
                }
            } elseif (array_key_exists('default', $dictionaryMemberInfo)) {
                $dictionary[$dictionaryMemberIdentifier] = $dictionaryMemberInfo['default'];
            } elseif (isset($dictionaryMemberInfo['required'])) {
                throw new \DomainException(sprintf(
                    'In "%s" member of %s, expected %s, got none',
                    $dictionaryMemberIdentifier,
                    $identifier,
                    $dictionaryMemberInfo['type']
                ));
            }
        }
        
        return $dictionary;
    }
    
    /**
     * 与えられた値を、{@link \esperecyan\webidl\Record} に変換して返します。
     * @link https://heycam.github.io/webidl/#idl-record Web IDL
     * @param mixed $traversable
     * @param string $keyType record のキーの型 (record<K, V\> の K)。
     * @param string $valueType record の値の型 (record<K, V\> の V)。
     * @param array $pseudoTypes
     * @throws \DomainException 与えられた配列のキーまたは値が、指定された型に合致しない場合。
     * @return Record
     */
    public static function toRecord($traversable, $keyType, $valueType, $pseudoTypes = [])
    {
        $exceptionMessage = ErrorMessageCreator::create(
            null,
            sprintf('%s (an associative array including only %s)', "record<$keyType, $valueType>", $valueType),
            ''
        );
        
        $entries = [];
        
        foreach (SequenceType::convertToRewindable($traversable) as $key => $value) {
            try {
                $entry[0] = Type::to($keyType, $key, $pseudoTypes);
            } catch (\LogicException $exception) {
                if ($exception instanceof \InvalidArgumentException || $exception instanceof \DomainException) {
                    throw new \DomainException($exceptionMessage, 0, $exception);
                } else {
                    throw $exception;
                }
            }
            
            try {
                $entry[1] = Type::to($valueType, $value, $pseudoTypes);
            } catch (\LogicException $exception) {
                if ($exception instanceof \InvalidArgumentException || $exception instanceof \DomainException) {
                    throw new \DomainException($exceptionMessage, 0, $exception);
                } else {
                    throw $exception;
                }
            }
            
            $entries[] = $entry;
        }
        
        return new Record($entries);
    }
}
esperecyan/webidl documentation API documentation generated by ApiGen